OLD | NEW |
(Empty) | |
| 1 // Copyright 2016 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 5 #include "src/builtins/builtins-constructor.h" |
| 6 #include "src/builtins/builtins-utils.h" |
| 7 #include "src/builtins/builtins.h" |
| 8 #include "src/code-factory.h" |
| 9 #include "src/code-stub-assembler.h" |
| 10 #include "src/interface-descriptors.h" |
| 11 |
| 12 namespace v8 { |
| 13 namespace internal { |
| 14 |
| 15 typedef compiler::Node Node; |
| 16 |
| 17 Node* ConstructorBuiltinsAssembler::EmitFastNewClosure(Node* shared_info, |
| 18 Node* context) { |
| 19 typedef compiler::CodeAssembler::Label Label; |
| 20 typedef compiler::CodeAssembler::Variable Variable; |
| 21 |
| 22 Isolate* isolate = this->isolate(); |
| 23 Factory* factory = isolate->factory(); |
| 24 IncrementCounter(isolate->counters()->fast_new_closure_total(), 1); |
| 25 |
| 26 // Create a new closure from the given function info in new space |
| 27 Node* result = Allocate(JSFunction::kSize); |
| 28 |
| 29 // Calculate the index of the map we should install on the function based on |
| 30 // the FunctionKind and LanguageMode of the function. |
| 31 // Note: Must be kept in sync with Context::FunctionMapIndex |
| 32 Node* compiler_hints = |
| 33 LoadObjectField(shared_info, SharedFunctionInfo::kCompilerHintsOffset, |
| 34 MachineType::Uint32()); |
| 35 Node* is_strict = Word32And( |
| 36 compiler_hints, Int32Constant(1 << SharedFunctionInfo::kStrictModeBit)); |
| 37 |
| 38 Label if_normal(this), if_generator(this), if_async(this), |
| 39 if_class_constructor(this), if_function_without_prototype(this), |
| 40 load_map(this); |
| 41 Variable map_index(this, MachineType::PointerRepresentation()); |
| 42 |
| 43 STATIC_ASSERT(FunctionKind::kNormalFunction == 0); |
| 44 Node* is_not_normal = |
| 45 Word32And(compiler_hints, |
| 46 Int32Constant(SharedFunctionInfo::kAllFunctionKindBitsMask)); |
| 47 GotoUnless(is_not_normal, &if_normal); |
| 48 |
| 49 Node* is_generator = Word32And( |
| 50 compiler_hints, Int32Constant(FunctionKind::kGeneratorFunction |
| 51 << SharedFunctionInfo::kFunctionKindShift)); |
| 52 GotoIf(is_generator, &if_generator); |
| 53 |
| 54 Node* is_async = Word32And( |
| 55 compiler_hints, Int32Constant(FunctionKind::kAsyncFunction |
| 56 << SharedFunctionInfo::kFunctionKindShift)); |
| 57 GotoIf(is_async, &if_async); |
| 58 |
| 59 Node* is_class_constructor = Word32And( |
| 60 compiler_hints, Int32Constant(FunctionKind::kClassConstructor |
| 61 << SharedFunctionInfo::kFunctionKindShift)); |
| 62 GotoIf(is_class_constructor, &if_class_constructor); |
| 63 |
| 64 if (FLAG_debug_code) { |
| 65 // Function must be a function without a prototype. |
| 66 CSA_ASSERT( |
| 67 this, |
| 68 Word32And(compiler_hints, |
| 69 Int32Constant((FunctionKind::kAccessorFunction | |
| 70 FunctionKind::kArrowFunction | |
| 71 FunctionKind::kConciseMethod) |
| 72 << SharedFunctionInfo::kFunctionKindShift))); |
| 73 } |
| 74 Goto(&if_function_without_prototype); |
| 75 |
| 76 Bind(&if_normal); |
| 77 { |
| 78 map_index.Bind(SelectIntPtrConstant(is_strict, |
| 79 Context::STRICT_FUNCTION_MAP_INDEX, |
| 80 Context::SLOPPY_FUNCTION_MAP_INDEX)); |
| 81 Goto(&load_map); |
| 82 } |
| 83 |
| 84 Bind(&if_generator); |
| 85 { |
| 86 map_index.Bind(SelectIntPtrConstant( |
| 87 is_strict, Context::STRICT_GENERATOR_FUNCTION_MAP_INDEX, |
| 88 Context::SLOPPY_GENERATOR_FUNCTION_MAP_INDEX)); |
| 89 Goto(&load_map); |
| 90 } |
| 91 |
| 92 Bind(&if_async); |
| 93 { |
| 94 map_index.Bind(SelectIntPtrConstant( |
| 95 is_strict, Context::STRICT_ASYNC_FUNCTION_MAP_INDEX, |
| 96 Context::SLOPPY_ASYNC_FUNCTION_MAP_INDEX)); |
| 97 Goto(&load_map); |
| 98 } |
| 99 |
| 100 Bind(&if_class_constructor); |
| 101 { |
| 102 map_index.Bind(IntPtrConstant(Context::CLASS_FUNCTION_MAP_INDEX)); |
| 103 Goto(&load_map); |
| 104 } |
| 105 |
| 106 Bind(&if_function_without_prototype); |
| 107 { |
| 108 map_index.Bind( |
| 109 IntPtrConstant(Context::STRICT_FUNCTION_WITHOUT_PROTOTYPE_MAP_INDEX)); |
| 110 Goto(&load_map); |
| 111 } |
| 112 |
| 113 Bind(&load_map); |
| 114 |
| 115 // Get the function map in the current native context and set that |
| 116 // as the map of the allocated object. |
| 117 Node* native_context = LoadNativeContext(context); |
| 118 Node* map_slot_value = |
| 119 LoadFixedArrayElement(native_context, map_index.value()); |
| 120 StoreMapNoWriteBarrier(result, map_slot_value); |
| 121 |
| 122 // Initialize the rest of the function. |
| 123 Node* empty_fixed_array = HeapConstant(factory->empty_fixed_array()); |
| 124 Node* empty_literals_array = HeapConstant(factory->empty_literals_array()); |
| 125 StoreObjectFieldNoWriteBarrier(result, JSObject::kPropertiesOffset, |
| 126 empty_fixed_array); |
| 127 StoreObjectFieldNoWriteBarrier(result, JSObject::kElementsOffset, |
| 128 empty_fixed_array); |
| 129 StoreObjectFieldNoWriteBarrier(result, JSFunction::kLiteralsOffset, |
| 130 empty_literals_array); |
| 131 StoreObjectFieldNoWriteBarrier( |
| 132 result, JSFunction::kPrototypeOrInitialMapOffset, TheHoleConstant()); |
| 133 StoreObjectFieldNoWriteBarrier(result, JSFunction::kSharedFunctionInfoOffset, |
| 134 shared_info); |
| 135 StoreObjectFieldNoWriteBarrier(result, JSFunction::kContextOffset, context); |
| 136 Handle<Code> lazy_builtin_handle( |
| 137 isolate->builtins()->builtin(Builtins::kCompileLazy)); |
| 138 Node* lazy_builtin = HeapConstant(lazy_builtin_handle); |
| 139 Node* lazy_builtin_entry = |
| 140 IntPtrAdd(BitcastTaggedToWord(lazy_builtin), |
| 141 IntPtrConstant(Code::kHeaderSize - kHeapObjectTag)); |
| 142 StoreObjectFieldNoWriteBarrier(result, JSFunction::kCodeEntryOffset, |
| 143 lazy_builtin_entry, |
| 144 MachineType::PointerRepresentation()); |
| 145 StoreObjectFieldNoWriteBarrier(result, JSFunction::kNextFunctionLinkOffset, |
| 146 UndefinedConstant()); |
| 147 |
| 148 return result; |
| 149 } |
| 150 |
| 151 TF_BUILTIN(FastNewClosure, ConstructorBuiltinsAssembler) { |
| 152 Node* shared = Parameter(FastNewClosureDescriptor::kSharedFunctionInfo); |
| 153 Node* context = Parameter(FastNewClosureDescriptor::kContext); |
| 154 Return(EmitFastNewClosure(shared, context)); |
| 155 } |
| 156 |
| 157 } // namespace internal |
| 158 } // namespace v8 |
OLD | NEW |