Index: src/builtins/builtins-constructor.cc |
diff --git a/src/builtins/builtins-constructor.cc b/src/builtins/builtins-constructor.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..d7bf3cccdae3183cc55f26d59b731e57f0242a72 |
--- /dev/null |
+++ b/src/builtins/builtins-constructor.cc |
@@ -0,0 +1,158 @@ |
+// Copyright 2016 the V8 project authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#include "src/builtins/builtins-constructor.h" |
+#include "src/builtins/builtins-utils.h" |
+#include "src/builtins/builtins.h" |
+#include "src/code-factory.h" |
+#include "src/code-stub-assembler.h" |
+#include "src/interface-descriptors.h" |
+ |
+namespace v8 { |
+namespace internal { |
+ |
+typedef compiler::Node Node; |
+ |
+Node* ConstructorBuiltinsAssembler::EmitFastNewClosure(Node* shared_info, |
+ Node* context) { |
+ typedef compiler::CodeAssembler::Label Label; |
+ typedef compiler::CodeAssembler::Variable Variable; |
+ |
+ Isolate* isolate = this->isolate(); |
+ Factory* factory = isolate->factory(); |
+ IncrementCounter(isolate->counters()->fast_new_closure_total(), 1); |
+ |
+ // Create a new closure from the given function info in new space |
+ Node* result = 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 = |
+ LoadObjectField(shared_info, SharedFunctionInfo::kCompilerHintsOffset, |
+ MachineType::Uint32()); |
+ Node* is_strict = Word32And( |
+ compiler_hints, Int32Constant(1 << SharedFunctionInfo::kStrictModeBit)); |
+ |
+ Label if_normal(this), if_generator(this), if_async(this), |
+ if_class_constructor(this), if_function_without_prototype(this), |
+ load_map(this); |
+ Variable map_index(this, MachineType::PointerRepresentation()); |
+ |
+ STATIC_ASSERT(FunctionKind::kNormalFunction == 0); |
+ Node* is_not_normal = |
+ Word32And(compiler_hints, |
+ Int32Constant(SharedFunctionInfo::kAllFunctionKindBitsMask)); |
+ GotoUnless(is_not_normal, &if_normal); |
+ |
+ Node* is_generator = Word32And( |
+ compiler_hints, Int32Constant(FunctionKind::kGeneratorFunction |
+ << SharedFunctionInfo::kFunctionKindShift)); |
+ GotoIf(is_generator, &if_generator); |
+ |
+ Node* is_async = Word32And( |
+ compiler_hints, Int32Constant(FunctionKind::kAsyncFunction |
+ << SharedFunctionInfo::kFunctionKindShift)); |
+ GotoIf(is_async, &if_async); |
+ |
+ Node* is_class_constructor = Word32And( |
+ compiler_hints, Int32Constant(FunctionKind::kClassConstructor |
+ << SharedFunctionInfo::kFunctionKindShift)); |
+ GotoIf(is_class_constructor, &if_class_constructor); |
+ |
+ if (FLAG_debug_code) { |
+ // Function must be a function without a prototype. |
+ CSA_ASSERT( |
+ this, |
+ Word32And(compiler_hints, |
+ Int32Constant((FunctionKind::kAccessorFunction | |
+ FunctionKind::kArrowFunction | |
+ FunctionKind::kConciseMethod) |
+ << SharedFunctionInfo::kFunctionKindShift))); |
+ } |
+ Goto(&if_function_without_prototype); |
+ |
+ Bind(&if_normal); |
+ { |
+ map_index.Bind(SelectIntPtrConstant(is_strict, |
+ Context::STRICT_FUNCTION_MAP_INDEX, |
+ Context::SLOPPY_FUNCTION_MAP_INDEX)); |
+ Goto(&load_map); |
+ } |
+ |
+ Bind(&if_generator); |
+ { |
+ map_index.Bind(SelectIntPtrConstant( |
+ is_strict, Context::STRICT_GENERATOR_FUNCTION_MAP_INDEX, |
+ Context::SLOPPY_GENERATOR_FUNCTION_MAP_INDEX)); |
+ Goto(&load_map); |
+ } |
+ |
+ Bind(&if_async); |
+ { |
+ map_index.Bind(SelectIntPtrConstant( |
+ is_strict, Context::STRICT_ASYNC_FUNCTION_MAP_INDEX, |
+ Context::SLOPPY_ASYNC_FUNCTION_MAP_INDEX)); |
+ Goto(&load_map); |
+ } |
+ |
+ Bind(&if_class_constructor); |
+ { |
+ map_index.Bind(IntPtrConstant(Context::CLASS_FUNCTION_MAP_INDEX)); |
+ Goto(&load_map); |
+ } |
+ |
+ Bind(&if_function_without_prototype); |
+ { |
+ map_index.Bind( |
+ IntPtrConstant(Context::STRICT_FUNCTION_WITHOUT_PROTOTYPE_MAP_INDEX)); |
+ Goto(&load_map); |
+ } |
+ |
+ 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 = LoadNativeContext(context); |
+ Node* map_slot_value = |
+ LoadFixedArrayElement(native_context, map_index.value()); |
+ StoreMapNoWriteBarrier(result, map_slot_value); |
+ |
+ // Initialize the rest of the function. |
+ Node* empty_fixed_array = HeapConstant(factory->empty_fixed_array()); |
+ Node* empty_literals_array = HeapConstant(factory->empty_literals_array()); |
+ StoreObjectFieldNoWriteBarrier(result, JSObject::kPropertiesOffset, |
+ empty_fixed_array); |
+ StoreObjectFieldNoWriteBarrier(result, JSObject::kElementsOffset, |
+ empty_fixed_array); |
+ StoreObjectFieldNoWriteBarrier(result, JSFunction::kLiteralsOffset, |
+ empty_literals_array); |
+ StoreObjectFieldNoWriteBarrier( |
+ result, JSFunction::kPrototypeOrInitialMapOffset, TheHoleConstant()); |
+ StoreObjectFieldNoWriteBarrier(result, JSFunction::kSharedFunctionInfoOffset, |
+ shared_info); |
+ StoreObjectFieldNoWriteBarrier(result, JSFunction::kContextOffset, context); |
+ Handle<Code> lazy_builtin_handle( |
+ isolate->builtins()->builtin(Builtins::kCompileLazy)); |
+ Node* lazy_builtin = HeapConstant(lazy_builtin_handle); |
+ Node* lazy_builtin_entry = |
+ IntPtrAdd(BitcastTaggedToWord(lazy_builtin), |
+ IntPtrConstant(Code::kHeaderSize - kHeapObjectTag)); |
+ StoreObjectFieldNoWriteBarrier(result, JSFunction::kCodeEntryOffset, |
+ lazy_builtin_entry, |
+ MachineType::PointerRepresentation()); |
+ StoreObjectFieldNoWriteBarrier(result, JSFunction::kNextFunctionLinkOffset, |
+ UndefinedConstant()); |
+ |
+ return result; |
+} |
+ |
+TF_BUILTIN(FastNewClosure, ConstructorBuiltinsAssembler) { |
+ Node* shared = Parameter(FastNewClosureDescriptor::kSharedFunctionInfo); |
+ Node* context = Parameter(FastNewClosureDescriptor::kContext); |
+ Return(EmitFastNewClosure(shared, context)); |
+} |
+ |
+} // namespace internal |
+} // namespace v8 |