Commit d21ed46d authored by cbruni's avatar cbruni Committed by Commit bot

[turbofan] Use fast stub for ForInPrepare and ForInNext

Review-Url: https://codereview.chromium.org/2684043002
Cr-Commit-Position: refs/heads/master@{#43040}
parent 2237106a
......@@ -910,6 +910,51 @@ TF_BUILTIN(ForInFilter, ObjectBuiltinsAssembler) {
Return(ForInFilter(key, object, context));
}
TF_BUILTIN(ForInNext, ObjectBuiltinsAssembler) {
typedef ForInNextDescriptor Descriptor;
Label filter(this);
Node* object = Parameter(Descriptor::kObject);
Node* cache_array = Parameter(Descriptor::kCacheArray);
Node* cache_type = Parameter(Descriptor::kCacheType);
Node* index = Parameter(Descriptor::kIndex);
Node* context = Parameter(Descriptor::kContext);
Node* key = LoadFixedArrayElement(cache_array, SmiUntag(index));
Node* map = LoadMap(object);
GotoUnless(WordEqual(map, cache_type), &filter);
Return(key);
Bind(&filter);
Return(ForInFilter(key, object, context));
}
TF_BUILTIN(ForInPrepare, ObjectBuiltinsAssembler) {
typedef ForInPrepareDescriptor Descriptor;
Label use_cache(this), nothing_to_iterate(this), call_runtime(this);
Node* object = Parameter(Descriptor::kObject);
Node* context = Parameter(Descriptor::kContext);
CheckEnumCache(object, &use_cache, &call_runtime);
Bind(&use_cache);
Node* map = LoadMap(object);
Node* enum_length = EnumLength(map);
GotoIf(WordEqual(enum_length, SmiConstant(0)), &nothing_to_iterate);
Node* descriptors = LoadMapDescriptors(map);
Node* cache_offset =
LoadObjectField(descriptors, DescriptorArray::kEnumCacheOffset);
Node* enum_cache = LoadObjectField(
cache_offset, DescriptorArray::kEnumCacheBridgeCacheOffset);
Return(map, enum_cache, enum_length);
Bind(&nothing_to_iterate);
Node* zero = SmiConstant(0);
Return(zero, zero, zero);
Bind(&call_runtime);
TailCallRuntime(Runtime::kForInPrepare, context, object);
}
TF_BUILTIN(InstanceOf, ObjectBuiltinsAssembler) {
typedef CompareDescriptor Descriptor;
......
......@@ -98,7 +98,8 @@ Code* BuildWithCodeStubAssemblerJS(Isolate* isolate,
Code* BuildWithCodeStubAssemblerCS(Isolate* isolate,
CodeAssemblerGenerator generator,
CallDescriptors::Key interface_descriptor,
Code::Flags flags, const char* name) {
Code::Flags flags, const char* name,
int result_size) {
HandleScope scope(isolate);
Zone zone(isolate->allocator(), ZONE_NAME);
// The interface descriptor with given key must be initialized at this point
......@@ -106,7 +107,8 @@ Code* BuildWithCodeStubAssemblerCS(Isolate* isolate,
CallInterfaceDescriptor descriptor(isolate, interface_descriptor);
// Ensure descriptor is already initialized.
DCHECK_LE(0, descriptor.GetRegisterParameterCount());
compiler::CodeAssemblerState state(isolate, &zone, descriptor, flags, name);
compiler::CodeAssemblerState state(isolate, &zone, descriptor, flags, name,
result_size);
generator(&state);
Handle<Code> code = compiler::CodeAssembler::GenerateCode(&state);
PostBuildProfileAndTracing(isolate, *code, name);
......@@ -136,11 +138,11 @@ void Builtins::SetUp(Isolate* isolate, bool create_heap_objects) {
code = BuildWithCodeStubAssemblerJS(isolate, &Generate_##Name, Argc, \
kBuiltinFlags, #Name); \
builtins_[index++] = code;
#define BUILD_TFS(Name, Kind, Extra, InterfaceDescriptor) \
#define BUILD_TFS(Name, Kind, Extra, InterfaceDescriptor, result_size) \
{ InterfaceDescriptor##Descriptor descriptor(isolate); } \
code = BuildWithCodeStubAssemblerCS( \
isolate, &Generate_##Name, CallDescriptors::InterfaceDescriptor, \
Code::ComputeFlags(Code::Kind, Extra), #Name); \
Code::ComputeFlags(Code::Kind, Extra), #Name, result_size); \
builtins_[index++] = code;
#define BUILD_ASM(Name) \
code = \
......
This diff is collapsed.
......@@ -193,7 +193,7 @@ Callable CodeFactory::StringFromCharCode(Isolate* isolate) {
return Callable(code, BuiltinDescriptor(isolate));
}
#define DECLARE_TFS(Name, Kind, Extra, InterfaceDescriptor) \
#define DECLARE_TFS(Name, Kind, Extra, InterfaceDescriptor, result_size) \
typedef InterfaceDescriptor##Descriptor Name##Descriptor;
BUILTIN_LIST(IGNORE_BUILTIN, IGNORE_BUILTIN, IGNORE_BUILTIN, DECLARE_TFS,
IGNORE_BUILTIN, IGNORE_BUILTIN, IGNORE_BUILTIN)
......@@ -363,6 +363,18 @@ Callable CodeFactory::FastNewStrictArguments(Isolate* isolate) {
FastNewRestParameterDescriptor(isolate));
}
// static
Callable CodeFactory::ForInPrepare(Isolate* isolate) {
return Callable(isolate->builtins()->ForInPrepare(),
ForInPrepareDescriptor(isolate));
}
// static
Callable CodeFactory::ForInNext(Isolate* isolate) {
return Callable(isolate->builtins()->ForInNext(),
ForInNextDescriptor(isolate));
}
// static
Callable CodeFactory::AllocateHeapNumber(Isolate* isolate) {
AllocateHeapNumberStub stub(isolate);
......
......@@ -152,6 +152,9 @@ class V8_EXPORT_PRIVATE CodeFactory final {
static Callable FastNewSloppyArguments(Isolate* isolate);
static Callable FastNewStrictArguments(Isolate* isolate);
static Callable ForInPrepare(Isolate* isolate);
static Callable ForInNext(Isolate* isolate);
static Callable CopyFastSmiOrObjectElements(Isolate* isolate);
static Callable GrowFastDoubleElements(Isolate* isolate);
static Callable GrowFastSmiOrObjectElements(Isolate* isolate);
......
......@@ -260,6 +260,14 @@ void CodeAssembler::Return(Node* value) {
return raw_assembler()->Return(value);
}
void CodeAssembler::Return(Node* value1, Node* value2) {
return raw_assembler()->Return(value1, value2);
}
void CodeAssembler::Return(Node* value1, Node* value2, Node* value3) {
return raw_assembler()->Return(value1, value2, value3);
}
void CodeAssembler::PopAndReturn(Node* pop, Node* value) {
return raw_assembler()->PopAndReturn(pop, value);
}
......
......@@ -229,6 +229,8 @@ class V8_EXPORT_PRIVATE CodeAssembler {
Node* Parameter(int value);
Node* GetJSContextParameter();
void Return(Node* value);
void Return(Node* value1, Node* value2);
void Return(Node* value1, Node* value2, Node* value3);
void PopAndReturn(Node* pop, Node* value);
void DebugBreak();
......
......@@ -88,11 +88,12 @@ void JSGenericLowering::ReplaceWithStubCall(Node* node, Callable callable,
void JSGenericLowering::ReplaceWithStubCall(Node* node, Callable callable,
CallDescriptor::Flags flags,
Operator::Properties properties) {
Operator::Properties properties,
int result_size) {
const CallInterfaceDescriptor& descriptor = callable.descriptor();
CallDescriptor* desc = Linkage::GetStubCallDescriptor(
isolate(), zone(), descriptor, descriptor.GetStackParameterCount(), flags,
properties);
properties, MachineType::AnyTagged(), result_size);
Node* stub_code = jsgraph()->HeapConstant(callable.code());
node->InsertInput(zone(), 0, stub_code);
NodeProperties::ChangeOp(node, common()->Call(desc));
......@@ -586,12 +587,15 @@ void JSGenericLowering::LowerJSConvertReceiver(Node* node) {
}
void JSGenericLowering::LowerJSForInNext(Node* node) {
ReplaceWithRuntimeCall(node, Runtime::kForInNext);
CallDescriptor::Flags flags = FrameStateFlagForCall(node);
Callable callable = CodeFactory::ForInNext(isolate());
ReplaceWithStubCall(node, callable, flags);
}
void JSGenericLowering::LowerJSForInPrepare(Node* node) {
ReplaceWithRuntimeCall(node, Runtime::kForInPrepare);
CallDescriptor::Flags flags = FrameStateFlagForCall(node);
Callable callable = CodeFactory::ForInPrepare(isolate());
ReplaceWithStubCall(node, callable, flags, node->op()->properties(), 3);
}
void JSGenericLowering::LowerJSLoadMessage(Node* node) {
......
......@@ -38,7 +38,8 @@ class JSGenericLowering final : public Reducer {
// Helpers to replace existing nodes with a generic call.
void ReplaceWithStubCall(Node* node, Callable c, CallDescriptor::Flags flags);
void ReplaceWithStubCall(Node* node, Callable c, CallDescriptor::Flags flags,
Operator::Properties properties);
Operator::Properties properties,
int result_size = 1);
void ReplaceWithRuntimeCall(Node* node, Runtime::FunctionId f, int args = -1);
Zone* zone() const;
......
......@@ -87,6 +87,8 @@ class PlatformInterfaceDescriptor;
V(CreateIterResultObject) \
V(HasProperty) \
V(ForInFilter) \
V(ForInNext) \
V(ForInPrepare) \
V(GetProperty) \
V(CallHandler) \
V(ArgumentAdaptor) \
......@@ -531,6 +533,20 @@ class ForInFilterDescriptor final : public CallInterfaceDescriptor {
kParameterCount)
};
class ForInNextDescriptor final : public CallInterfaceDescriptor {
public:
DEFINE_PARAMETERS(kObject, kCacheArray, kCacheType, kIndex)
DECLARE_DEFAULT_DESCRIPTOR(ForInNextDescriptor, CallInterfaceDescriptor,
kParameterCount)
};
class ForInPrepareDescriptor final : public CallInterfaceDescriptor {
public:
DEFINE_PARAMETERS(kObject)
DECLARE_DEFAULT_DESCRIPTOR(ForInPrepareDescriptor, CallInterfaceDescriptor,
kParameterCount)
};
class GetPropertyDescriptor final : public CallInterfaceDescriptor {
public:
DEFINE_PARAMETERS(kObject, kKey)
......
......@@ -160,22 +160,5 @@ RUNTIME_FUNCTION(Runtime_ForInFilter) {
HasEnumerableProperty(isolate, receiver, key));
}
RUNTIME_FUNCTION(Runtime_ForInNext) {
HandleScope scope(isolate);
DCHECK_EQ(4, args.length());
CONVERT_ARG_HANDLE_CHECKED(JSReceiver, receiver, 0);
CONVERT_ARG_HANDLE_CHECKED(FixedArray, cache_array, 1);
CONVERT_ARG_HANDLE_CHECKED(Object, cache_type, 2);
CONVERT_SMI_ARG_CHECKED(index, 3);
Handle<Object> key = handle(cache_array->get(index), isolate);
// Don't need filtering if expected map still matches that of the receiver.
if (receiver->map() == *cache_type) {
return *key;
}
RETURN_RESULT_OR_FAILURE(isolate,
HasEnumerableProperty(isolate, receiver, key));
}
} // namespace internal
} // namespace v8
......@@ -209,8 +209,7 @@ namespace internal {
#define FOR_EACH_INTRINSIC_FORIN(F) \
F(ForInEnumerate, 1, 1) \
F(ForInFilter, 2, 1) \
F(ForInHasProperty, 2, 1) \
F(ForInNext, 4, 1)
F(ForInHasProperty, 2, 1)
#define FOR_EACH_INTRINSIC_INTERPRETER(F) \
F(InterpreterNewClosure, 4, 1) \
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment