Index: src/code-stubs.cc |
diff --git a/src/code-stubs.cc b/src/code-stubs.cc |
index a4d91a9fa23b2de35911a4e3fa85754b5cdc957b..d066e1cf444957e93ed7ad8f9630b99c853c8fdb 100644 |
--- a/src/code-stubs.cc |
+++ b/src/code-stubs.cc |
@@ -4189,14 +4189,10 @@ ElementsTransitionAndStoreStub::GetCallInterfaceDescriptor() const { |
return VectorStoreTransitionDescriptor(isolate()); |
} |
-void FastNewClosureStub::InitializeDescriptor(CodeStubDescriptor* descriptor) {} |
- |
void FastNewContextStub::InitializeDescriptor(CodeStubDescriptor* d) {} |
- |
void TypeofStub::InitializeDescriptor(CodeStubDescriptor* descriptor) {} |
- |
void NumberToStringStub::InitializeDescriptor(CodeStubDescriptor* descriptor) { |
descriptor->Initialize( |
Runtime::FunctionForId(Runtime::kNumberToString)->entry); |
@@ -4425,6 +4421,154 @@ compiler::Node* HasPropertyStub::Generate(CodeStubAssembler* assembler, |
return result.value(); |
} |
+// static |
+compiler::Node* FastNewClosureStub::Generate(CodeStubAssembler* assembler, |
+ compiler::Node* shared_info, |
+ compiler::Node* context) { |
+ typedef compiler::Node Node; |
+ typedef compiler::CodeAssembler::Label Label; |
+ typedef compiler::CodeAssembler::Variable Variable; |
+ |
+ Isolate* isolate = assembler->isolate(); |
+ Factory* factory = assembler->isolate()->factory(); |
+ assembler->IncrementCounter(isolate->counters()->fast_new_closure_total(), 1); |
+ |
+ // Create a new closure from the given function info in new space |
+ Node* result = assembler->Allocate(JSFunction::kSize); |
+ |
+ // Calculate the index of the map we should install on the function based on |
+ // the FunctionKind and LanguageMode of the function. |
+ // Note: Must be kept in sync with Context::FunctionMapIndex |
+ Node* compiler_hints = assembler->LoadObjectField( |
+ shared_info, SharedFunctionInfo::kCompilerHintsOffset, |
+ MachineType::Uint32()); |
+ Node* is_strict = assembler->Word32And( |
+ compiler_hints, |
+ assembler->Int32Constant(1 << SharedFunctionInfo::kStrictModeBit)); |
+ |
+ Label if_normal(assembler), if_generator(assembler), if_async(assembler), |
+ if_class_constructor(assembler), if_function_without_prototype(assembler), |
+ load_map(assembler); |
+ Variable map_index(assembler, MachineRepresentation::kTagged); |
+ |
+ Node* is_not_normal = assembler->Word32And( |
+ compiler_hints, |
+ assembler->Int32Constant(SharedFunctionInfo::kFunctionKindMaskBits)); |
+ assembler->GotoUnless(is_not_normal, &if_normal); |
+ |
+ Node* is_generator = assembler->Word32And( |
+ compiler_hints, |
+ assembler->Int32Constant(1 << SharedFunctionInfo::kIsGeneratorBit)); |
+ assembler->GotoIf(is_generator, &if_generator); |
+ |
+ Node* is_async = assembler->Word32And( |
+ compiler_hints, |
+ assembler->Int32Constant(1 << SharedFunctionInfo::kIsAsyncFunctionBit)); |
+ assembler->GotoIf(is_async, &if_async); |
+ |
+ Node* is_class_constructor = assembler->Word32And( |
+ compiler_hints, |
+ assembler->Int32Constant(SharedFunctionInfo::kClassConstructorBits)); |
+ assembler->GotoIf(is_class_constructor, &if_class_constructor); |
+ |
+ if (FLAG_debug_code) { |
+ // Function must be a function without a prototype. |
+ assembler->Assert(assembler->Word32And( |
+ compiler_hints, assembler->Int32Constant( |
+ SharedFunctionInfo::kAccessorFunctionBits | |
+ (1 << SharedFunctionInfo::kIsArrowBit) | |
+ (1 << SharedFunctionInfo::kIsConciseMethodBit)))); |
+ } |
+ assembler->Goto(&if_function_without_prototype); |
+ |
+ assembler->Bind(&if_normal); |
+ { |
+ map_index.Bind(assembler->Select( |
+ is_strict, assembler->Int32Constant(Context::STRICT_FUNCTION_MAP_INDEX), |
+ assembler->Int32Constant(Context::SLOPPY_FUNCTION_MAP_INDEX))); |
+ assembler->Goto(&load_map); |
+ } |
+ |
+ assembler->Bind(&if_generator); |
+ { |
+ map_index.Bind(assembler->Select( |
+ is_strict, |
+ assembler->Int32Constant(Context::STRICT_GENERATOR_FUNCTION_MAP_INDEX), |
+ assembler->Int32Constant( |
+ Context::SLOPPY_GENERATOR_FUNCTION_MAP_INDEX))); |
+ assembler->Goto(&load_map); |
+ } |
+ |
+ assembler->Bind(&if_async); |
+ { |
+ map_index.Bind(assembler->Select( |
+ is_strict, |
+ assembler->Int32Constant(Context::STRICT_ASYNC_FUNCTION_MAP_INDEX), |
+ assembler->Int32Constant(Context::SLOPPY_ASYNC_FUNCTION_MAP_INDEX))); |
+ assembler->Goto(&load_map); |
+ } |
+ |
+ assembler->Bind(&if_class_constructor); |
+ { |
+ map_index.Bind( |
+ assembler->Int32Constant(Context::STRICT_FUNCTION_MAP_INDEX)); |
+ assembler->Goto(&load_map); |
+ } |
+ |
+ assembler->Bind(&if_function_without_prototype); |
+ { |
+ map_index.Bind(assembler->Int32Constant( |
+ Context::STRICT_FUNCTION_WITHOUT_PROTOTYPE_MAP_INDEX)); |
+ assembler->Goto(&load_map); |
+ } |
+ |
+ assembler->Bind(&load_map); |
+ |
+ // Get the function map in the current native context and set that |
+ // as the map of the allocated object. |
+ Node* native_context = assembler->LoadNativeContext(context); |
+ Node* map_slot_value = |
+ assembler->LoadFixedArrayElement(native_context, map_index.value()); |
+ assembler->StoreMapNoWriteBarrier(result, map_slot_value); |
+ |
+ // Initialize the rest of the function. |
+ Node* empty_fixed_array = |
+ assembler->HeapConstant(factory->empty_fixed_array()); |
+ Node* empty_literals_array = |
+ assembler->HeapConstant(factory->empty_literals_array()); |
+ assembler->StoreObjectFieldNoWriteBarrier(result, JSObject::kPropertiesOffset, |
+ empty_fixed_array); |
+ assembler->StoreObjectFieldNoWriteBarrier(result, JSObject::kElementsOffset, |
+ empty_fixed_array); |
+ assembler->StoreObjectFieldNoWriteBarrier(result, JSFunction::kLiteralsOffset, |
+ empty_literals_array); |
+ assembler->StoreObjectFieldNoWriteBarrier( |
+ result, JSFunction::kPrototypeOrInitialMapOffset, |
+ assembler->TheHoleConstant()); |
+ assembler->StoreObjectFieldNoWriteBarrier( |
+ result, JSFunction::kSharedFunctionInfoOffset, shared_info); |
+ assembler->StoreObjectFieldNoWriteBarrier(result, JSFunction::kContextOffset, |
+ context); |
+ Handle<Code> lazy_builtin_handle( |
+ assembler->isolate()->builtins()->builtin(Builtins::kCompileLazy)); |
+ Node* lazy_builtin = assembler->HeapConstant(lazy_builtin_handle); |
+ Node* lazy_builtin_entry = assembler->IntPtrAdd( |
+ lazy_builtin, |
+ assembler->IntPtrConstant(Code::kHeaderSize - kHeapObjectTag)); |
+ assembler->StoreObjectFieldNoWriteBarrier( |
+ result, JSFunction::kCodeEntryOffset, lazy_builtin_entry); |
+ assembler->StoreObjectFieldNoWriteBarrier(result, |
+ JSFunction::kNextFunctionLinkOffset, |
+ assembler->UndefinedConstant()); |
+ |
+ return result; |
+} |
+ |
+void FastNewClosureStub::GenerateAssembly(CodeStubAssembler* assembler) const { |
+ assembler->Return( |
+ Generate(assembler, assembler->Parameter(0), assembler->Parameter(1))); |
+} |
+ |
void CreateAllocationSiteStub::GenerateAheadOfTime(Isolate* isolate) { |
CreateAllocationSiteStub stub(isolate); |
stub.GetCode(); |