Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(44)

Unified Diff: src/builtins/builtins-constructor.cc

Issue 2752143004: [refactor] Separate generated builtins and C++ builtins into separate files (Closed)
Patch Set: tentative gcmole fix Created 3 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/builtins/builtins-constructor.h ('k') | src/builtins/builtins-constructor-gen.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/builtins/builtins-constructor.cc
diff --git a/src/builtins/builtins-constructor.cc b/src/builtins/builtins-constructor.cc
deleted file mode 100644
index 0d303c90c156b3dad8c11e8dc70469bfe49ea05a..0000000000000000000000000000000000000000
--- a/src/builtins/builtins-constructor.cc
+++ /dev/null
@@ -1,794 +0,0 @@
-// 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/ast/ast.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/counters.h"
-#include "src/interface-descriptors.h"
-#include "src/objects-inl.h"
-
-namespace v8 {
-namespace internal {
-
-typedef compiler::Node Node;
-
-Node* ConstructorBuiltinsAssembler::EmitFastNewClosure(Node* shared_info,
- Node* feedback_vector,
- Node* slot,
- 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));
- GotoIfNot(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(IntPtrConstant(Context::GENERATOR_FUNCTION_MAP_INDEX));
- Goto(&load_map);
- }
-
- Bind(&if_async);
- {
- map_index.Bind(IntPtrConstant(Context::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());
- StoreObjectFieldNoWriteBarrier(result, JSObject::kPropertiesOffset,
- empty_fixed_array);
- StoreObjectFieldNoWriteBarrier(result, JSObject::kElementsOffset,
- empty_fixed_array);
- Node* literals_cell = LoadFixedArrayElement(
- feedback_vector, slot, 0, CodeStubAssembler::SMI_PARAMETERS);
- {
- // Bump the closure counter encoded in the cell's map.
- Node* cell_map = LoadMap(literals_cell);
- Label no_closures(this), one_closure(this), cell_done(this);
-
- GotoIf(IsNoClosuresCellMap(cell_map), &no_closures);
- GotoIf(IsOneClosureCellMap(cell_map), &one_closure);
- CSA_ASSERT(this, IsManyClosuresCellMap(cell_map));
- Goto(&cell_done);
-
- Bind(&no_closures);
- StoreMapNoWriteBarrier(literals_cell, Heap::kOneClosureCellMapRootIndex);
- Goto(&cell_done);
-
- Bind(&one_closure);
- StoreMapNoWriteBarrier(literals_cell, Heap::kManyClosuresCellMapRootIndex);
- Goto(&cell_done);
-
- Bind(&cell_done);
- }
- StoreObjectFieldNoWriteBarrier(result, JSFunction::kFeedbackVectorOffset,
- literals_cell);
- 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);
- Node* vector = Parameter(FastNewClosureDescriptor::kVector);
- Node* slot = Parameter(FastNewClosureDescriptor::kSlot);
- Return(EmitFastNewClosure(shared, vector, slot, context));
-}
-
-TF_BUILTIN(FastNewObject, ConstructorBuiltinsAssembler) {
- typedef FastNewObjectDescriptor Descriptor;
- Node* context = Parameter(Descriptor::kContext);
- Node* target = Parameter(Descriptor::kTarget);
- Node* new_target = Parameter(Descriptor::kNewTarget);
-
- Label call_runtime(this);
-
- Node* result = EmitFastNewObject(context, target, new_target, &call_runtime);
- Return(result);
-
- Bind(&call_runtime);
- TailCallRuntime(Runtime::kNewObject, context, target, new_target);
-}
-
-Node* ConstructorBuiltinsAssembler::EmitFastNewObject(Node* context,
- Node* target,
- Node* new_target) {
- Variable var_obj(this, MachineRepresentation::kTagged);
- Label call_runtime(this), end(this);
-
- Node* result = EmitFastNewObject(context, target, new_target, &call_runtime);
- var_obj.Bind(result);
- Goto(&end);
-
- Bind(&call_runtime);
- var_obj.Bind(CallRuntime(Runtime::kNewObject, context, target, new_target));
- Goto(&end);
-
- Bind(&end);
- return var_obj.value();
-}
-
-Node* ConstructorBuiltinsAssembler::EmitFastNewObject(
- Node* context, Node* target, Node* new_target,
- CodeAssemblerLabel* call_runtime) {
- CSA_ASSERT(this, HasInstanceType(target, JS_FUNCTION_TYPE));
- CSA_ASSERT(this, IsJSReceiver(new_target));
-
- // Verify that the new target is a JSFunction.
- Label fast(this), end(this);
- GotoIf(HasInstanceType(new_target, JS_FUNCTION_TYPE), &fast);
- Goto(call_runtime);
-
- Bind(&fast);
-
- // Load the initial map and verify that it's in fact a map.
- Node* initial_map =
- LoadObjectField(new_target, JSFunction::kPrototypeOrInitialMapOffset);
- GotoIf(TaggedIsSmi(initial_map), call_runtime);
- GotoIf(DoesntHaveInstanceType(initial_map, MAP_TYPE), call_runtime);
-
- // Fall back to runtime if the target differs from the new target's
- // initial map constructor.
- Node* new_target_constructor =
- LoadObjectField(initial_map, Map::kConstructorOrBackPointerOffset);
- GotoIf(WordNotEqual(target, new_target_constructor), call_runtime);
-
- Variable properties(this, MachineRepresentation::kTagged);
-
- Label instantiate_map(this), allocate_properties(this);
- GotoIf(IsDictionaryMap(initial_map), &allocate_properties);
- {
- properties.Bind(EmptyFixedArrayConstant());
- Goto(&instantiate_map);
- }
- Bind(&allocate_properties);
- {
- properties.Bind(AllocateNameDictionary(NameDictionary::kInitialCapacity));
- Goto(&instantiate_map);
- }
-
- Bind(&instantiate_map);
-
- Node* object = AllocateJSObjectFromMap(initial_map, properties.value());
-
- Node* instance_size_words = ChangeUint32ToWord(LoadObjectField(
- initial_map, Map::kInstanceSizeOffset, MachineType::Uint8()));
- Node* instance_size =
- WordShl(instance_size_words, IntPtrConstant(kPointerSizeLog2));
-
- // Perform in-object slack tracking if requested.
- Node* bit_field3 = LoadMapBitField3(initial_map);
- Label slack_tracking(this), finalize(this, Label::kDeferred), done(this);
- GotoIf(IsSetWord32<Map::ConstructionCounter>(bit_field3), &slack_tracking);
-
- // Initialize remaining fields.
- {
- Comment("no slack tracking");
- InitializeFieldsWithRoot(object, IntPtrConstant(JSObject::kHeaderSize),
- instance_size, Heap::kUndefinedValueRootIndex);
- Goto(&end);
- }
-
- {
- Bind(&slack_tracking);
-
- // Decrease generous allocation count.
- STATIC_ASSERT(Map::ConstructionCounter::kNext == 32);
- Comment("update allocation count");
- Node* new_bit_field3 = Int32Sub(
- bit_field3, Int32Constant(1 << Map::ConstructionCounter::kShift));
- StoreObjectFieldNoWriteBarrier(initial_map, Map::kBitField3Offset,
- new_bit_field3,
- MachineRepresentation::kWord32);
- GotoIf(IsClearWord32<Map::ConstructionCounter>(new_bit_field3), &finalize);
-
- Node* unused_fields = LoadObjectField(
- initial_map, Map::kUnusedPropertyFieldsOffset, MachineType::Uint8());
- Node* used_size =
- IntPtrSub(instance_size, WordShl(ChangeUint32ToWord(unused_fields),
- IntPtrConstant(kPointerSizeLog2)));
-
- Comment("initialize filler fields (no finalize)");
- InitializeFieldsWithRoot(object, used_size, instance_size,
- Heap::kOnePointerFillerMapRootIndex);
-
- Comment("initialize undefined fields (no finalize)");
- InitializeFieldsWithRoot(object, IntPtrConstant(JSObject::kHeaderSize),
- used_size, Heap::kUndefinedValueRootIndex);
- Goto(&end);
- }
-
- {
- // Finalize the instance size.
- Bind(&finalize);
-
- Node* unused_fields = LoadObjectField(
- initial_map, Map::kUnusedPropertyFieldsOffset, MachineType::Uint8());
- Node* used_size =
- IntPtrSub(instance_size, WordShl(ChangeUint32ToWord(unused_fields),
- IntPtrConstant(kPointerSizeLog2)));
-
- Comment("initialize filler fields (finalize)");
- InitializeFieldsWithRoot(object, used_size, instance_size,
- Heap::kOnePointerFillerMapRootIndex);
-
- Comment("initialize undefined fields (finalize)");
- InitializeFieldsWithRoot(object, IntPtrConstant(JSObject::kHeaderSize),
- used_size, Heap::kUndefinedValueRootIndex);
-
- CallRuntime(Runtime::kFinalizeInstanceSize, context, initial_map);
- Goto(&end);
- }
-
- Bind(&end);
- return object;
-}
-
-Node* ConstructorBuiltinsAssembler::EmitFastNewFunctionContext(
- Node* function, Node* slots, Node* context, ScopeType scope_type) {
- slots = ChangeUint32ToWord(slots);
-
- // TODO(ishell): Use CSA::OptimalParameterMode() here.
- CodeStubAssembler::ParameterMode mode = CodeStubAssembler::INTPTR_PARAMETERS;
- Node* min_context_slots = IntPtrConstant(Context::MIN_CONTEXT_SLOTS);
- Node* length = IntPtrAdd(slots, min_context_slots);
- Node* size = GetFixedArrayAllocationSize(length, FAST_ELEMENTS, mode);
-
- // Create a new closure from the given function info in new space
- Node* function_context = AllocateInNewSpace(size);
-
- Heap::RootListIndex context_type;
- switch (scope_type) {
- case EVAL_SCOPE:
- context_type = Heap::kEvalContextMapRootIndex;
- break;
- case FUNCTION_SCOPE:
- context_type = Heap::kFunctionContextMapRootIndex;
- break;
- default:
- UNREACHABLE();
- }
- StoreMapNoWriteBarrier(function_context, context_type);
- StoreObjectFieldNoWriteBarrier(function_context, Context::kLengthOffset,
- SmiTag(length));
-
- // Set up the fixed slots.
- StoreFixedArrayElement(function_context, Context::CLOSURE_INDEX, function,
- SKIP_WRITE_BARRIER);
- StoreFixedArrayElement(function_context, Context::PREVIOUS_INDEX, context,
- SKIP_WRITE_BARRIER);
- StoreFixedArrayElement(function_context, Context::EXTENSION_INDEX,
- TheHoleConstant(), SKIP_WRITE_BARRIER);
-
- // Copy the native context from the previous context.
- Node* native_context = LoadNativeContext(context);
- StoreFixedArrayElement(function_context, Context::NATIVE_CONTEXT_INDEX,
- native_context, SKIP_WRITE_BARRIER);
-
- // Initialize the rest of the slots to undefined.
- Node* undefined = UndefinedConstant();
- BuildFastFixedArrayForEach(
- function_context, FAST_ELEMENTS, min_context_slots, length,
- [this, undefined](Node* context, Node* offset) {
- StoreNoWriteBarrier(MachineRepresentation::kTagged, context, offset,
- undefined);
- },
- mode);
-
- return function_context;
-}
-
-// static
-int ConstructorBuiltinsAssembler::MaximumFunctionContextSlots() {
- return FLAG_test_small_max_function_context_stub_size ? kSmallMaximumSlots
- : kMaximumSlots;
-}
-
-TF_BUILTIN(FastNewFunctionContextEval, ConstructorBuiltinsAssembler) {
- Node* function = Parameter(FastNewFunctionContextDescriptor::kFunction);
- Node* slots = Parameter(FastNewFunctionContextDescriptor::kSlots);
- Node* context = Parameter(FastNewFunctionContextDescriptor::kContext);
- Return(EmitFastNewFunctionContext(function, slots, context,
- ScopeType::EVAL_SCOPE));
-}
-
-TF_BUILTIN(FastNewFunctionContextFunction, ConstructorBuiltinsAssembler) {
- Node* function = Parameter(FastNewFunctionContextDescriptor::kFunction);
- Node* slots = Parameter(FastNewFunctionContextDescriptor::kSlots);
- Node* context = Parameter(FastNewFunctionContextDescriptor::kContext);
- Return(EmitFastNewFunctionContext(function, slots, context,
- ScopeType::FUNCTION_SCOPE));
-}
-
-Handle<Code> Builtins::NewFunctionContext(ScopeType scope_type) {
- switch (scope_type) {
- case ScopeType::EVAL_SCOPE:
- return FastNewFunctionContextEval();
- case ScopeType::FUNCTION_SCOPE:
- return FastNewFunctionContextFunction();
- default:
- UNREACHABLE();
- }
- return Handle<Code>::null();
-}
-
-Node* ConstructorBuiltinsAssembler::EmitFastCloneRegExp(Node* closure,
- Node* literal_index,
- Node* pattern,
- Node* flags,
- Node* context) {
- typedef CodeStubAssembler::Label Label;
- typedef CodeStubAssembler::Variable Variable;
- typedef compiler::Node Node;
-
- Label call_runtime(this, Label::kDeferred), end(this);
-
- Variable result(this, MachineRepresentation::kTagged);
-
- Node* cell = LoadObjectField(closure, JSFunction::kFeedbackVectorOffset);
- Node* feedback_vector = LoadObjectField(cell, Cell::kValueOffset);
- Node* boilerplate = LoadFixedArrayElement(feedback_vector, literal_index, 0,
- CodeStubAssembler::SMI_PARAMETERS);
- GotoIf(IsUndefined(boilerplate), &call_runtime);
-
- {
- int size = JSRegExp::kSize + JSRegExp::kInObjectFieldCount * kPointerSize;
- Node* copy = Allocate(size);
- for (int offset = 0; offset < size; offset += kPointerSize) {
- Node* value = LoadObjectField(boilerplate, offset);
- StoreObjectFieldNoWriteBarrier(copy, offset, value);
- }
- result.Bind(copy);
- Goto(&end);
- }
-
- Bind(&call_runtime);
- {
- result.Bind(CallRuntime(Runtime::kCreateRegExpLiteral, context, closure,
- literal_index, pattern, flags));
- Goto(&end);
- }
-
- Bind(&end);
- return result.value();
-}
-
-TF_BUILTIN(FastCloneRegExp, ConstructorBuiltinsAssembler) {
- Node* closure = Parameter(FastCloneRegExpDescriptor::kClosure);
- Node* literal_index = Parameter(FastCloneRegExpDescriptor::kLiteralIndex);
- Node* pattern = Parameter(FastCloneRegExpDescriptor::kPattern);
- Node* flags = Parameter(FastCloneRegExpDescriptor::kFlags);
- Node* context = Parameter(FastCloneRegExpDescriptor::kContext);
-
- Return(EmitFastCloneRegExp(closure, literal_index, pattern, flags, context));
-}
-
-Node* ConstructorBuiltinsAssembler::NonEmptyShallowClone(
- Node* boilerplate, Node* boilerplate_map, Node* boilerplate_elements,
- Node* allocation_site, Node* capacity, ElementsKind kind) {
- typedef CodeStubAssembler::ParameterMode ParameterMode;
-
- ParameterMode param_mode = OptimalParameterMode();
-
- Node* length = LoadJSArrayLength(boilerplate);
- capacity = TaggedToParameter(capacity, param_mode);
-
- Node *array, *elements;
- std::tie(array, elements) = AllocateUninitializedJSArrayWithElements(
- kind, boilerplate_map, length, allocation_site, capacity, param_mode);
-
- Comment("copy elements header");
- // Header consists of map and length.
- STATIC_ASSERT(FixedArrayBase::kHeaderSize == 2 * kPointerSize);
- StoreMap(elements, LoadMap(boilerplate_elements));
- {
- int offset = FixedArrayBase::kLengthOffset;
- StoreObjectFieldNoWriteBarrier(
- elements, offset, LoadObjectField(boilerplate_elements, offset));
- }
-
- length = TaggedToParameter(length, param_mode);
-
- Comment("copy boilerplate elements");
- CopyFixedArrayElements(kind, boilerplate_elements, elements, length,
- SKIP_WRITE_BARRIER, param_mode);
- IncrementCounter(isolate()->counters()->inlined_copied_elements(), 1);
-
- return array;
-}
-
-Node* ConstructorBuiltinsAssembler::EmitFastCloneShallowArray(
- Node* closure, Node* literal_index, Node* context,
- CodeAssemblerLabel* call_runtime, AllocationSiteMode allocation_site_mode) {
- typedef CodeStubAssembler::Label Label;
- typedef CodeStubAssembler::Variable Variable;
- typedef compiler::Node Node;
-
- Label zero_capacity(this), cow_elements(this), fast_elements(this),
- return_result(this);
- Variable result(this, MachineRepresentation::kTagged);
-
- Node* cell = LoadObjectField(closure, JSFunction::kFeedbackVectorOffset);
- Node* feedback_vector = LoadObjectField(cell, Cell::kValueOffset);
- Node* allocation_site = LoadFixedArrayElement(
- feedback_vector, literal_index, 0, CodeStubAssembler::SMI_PARAMETERS);
-
- GotoIf(IsUndefined(allocation_site), call_runtime);
- allocation_site = LoadFixedArrayElement(feedback_vector, literal_index, 0,
- CodeStubAssembler::SMI_PARAMETERS);
-
- Node* boilerplate =
- LoadObjectField(allocation_site, AllocationSite::kTransitionInfoOffset);
- Node* boilerplate_map = LoadMap(boilerplate);
- Node* boilerplate_elements = LoadElements(boilerplate);
- Node* capacity = LoadFixedArrayBaseLength(boilerplate_elements);
- allocation_site =
- allocation_site_mode == TRACK_ALLOCATION_SITE ? allocation_site : nullptr;
-
- Node* zero = SmiConstant(Smi::kZero);
- GotoIf(SmiEqual(capacity, zero), &zero_capacity);
-
- Node* elements_map = LoadMap(boilerplate_elements);
- GotoIf(IsFixedCOWArrayMap(elements_map), &cow_elements);
-
- GotoIf(IsFixedArrayMap(elements_map), &fast_elements);
- {
- Comment("fast double elements path");
- if (FLAG_debug_code) {
- Label correct_elements_map(this), abort(this, Label::kDeferred);
- Branch(IsFixedDoubleArrayMap(elements_map), &correct_elements_map,
- &abort);
-
- Bind(&abort);
- {
- Node* abort_id = SmiConstant(
- Smi::FromInt(BailoutReason::kExpectedFixedDoubleArrayMap));
- CallRuntime(Runtime::kAbort, context, abort_id);
- result.Bind(UndefinedConstant());
- Goto(&return_result);
- }
- Bind(&correct_elements_map);
- }
-
- Node* array =
- NonEmptyShallowClone(boilerplate, boilerplate_map, boilerplate_elements,
- allocation_site, capacity, FAST_DOUBLE_ELEMENTS);
- result.Bind(array);
- Goto(&return_result);
- }
-
- Bind(&fast_elements);
- {
- Comment("fast elements path");
- Node* array =
- NonEmptyShallowClone(boilerplate, boilerplate_map, boilerplate_elements,
- allocation_site, capacity, FAST_ELEMENTS);
- result.Bind(array);
- Goto(&return_result);
- }
-
- Variable length(this, MachineRepresentation::kTagged),
- elements(this, MachineRepresentation::kTagged);
- Label allocate_without_elements(this);
-
- Bind(&cow_elements);
- {
- Comment("fixed cow path");
- length.Bind(LoadJSArrayLength(boilerplate));
- elements.Bind(boilerplate_elements);
-
- Goto(&allocate_without_elements);
- }
-
- Bind(&zero_capacity);
- {
- Comment("zero capacity path");
- length.Bind(zero);
- elements.Bind(LoadRoot(Heap::kEmptyFixedArrayRootIndex));
-
- Goto(&allocate_without_elements);
- }
-
- Bind(&allocate_without_elements);
- {
- Node* array = AllocateUninitializedJSArrayWithoutElements(
- FAST_ELEMENTS, boilerplate_map, length.value(), allocation_site);
- StoreObjectField(array, JSObject::kElementsOffset, elements.value());
- result.Bind(array);
- Goto(&return_result);
- }
-
- Bind(&return_result);
- return result.value();
-}
-
-void ConstructorBuiltinsAssembler::CreateFastCloneShallowArrayBuiltin(
- AllocationSiteMode allocation_site_mode) {
- typedef compiler::Node Node;
- typedef CodeStubAssembler::Label Label;
-
- Node* closure = Parameter(FastCloneShallowArrayDescriptor::kClosure);
- Node* literal_index =
- Parameter(FastCloneShallowArrayDescriptor::kLiteralIndex);
- Node* constant_elements =
- Parameter(FastCloneShallowArrayDescriptor::kConstantElements);
- Node* context = Parameter(FastCloneShallowArrayDescriptor::kContext);
- Label call_runtime(this, Label::kDeferred);
- Return(EmitFastCloneShallowArray(closure, literal_index, context,
- &call_runtime, allocation_site_mode));
-
- Bind(&call_runtime);
- {
- Comment("call runtime");
- Node* flags =
- SmiConstant(Smi::FromInt(ArrayLiteral::kShallowElements |
- (allocation_site_mode == TRACK_ALLOCATION_SITE
- ? 0
- : ArrayLiteral::kDisableMementos)));
- Return(CallRuntime(Runtime::kCreateArrayLiteral, context, closure,
- literal_index, constant_elements, flags));
- }
-}
-
-TF_BUILTIN(FastCloneShallowArrayTrack, ConstructorBuiltinsAssembler) {
- CreateFastCloneShallowArrayBuiltin(TRACK_ALLOCATION_SITE);
-}
-
-TF_BUILTIN(FastCloneShallowArrayDontTrack, ConstructorBuiltinsAssembler) {
- CreateFastCloneShallowArrayBuiltin(DONT_TRACK_ALLOCATION_SITE);
-}
-
-Handle<Code> Builtins::NewCloneShallowArray(
- AllocationSiteMode allocation_mode) {
- switch (allocation_mode) {
- case TRACK_ALLOCATION_SITE:
- return FastCloneShallowArrayTrack();
- case DONT_TRACK_ALLOCATION_SITE:
- return FastCloneShallowArrayDontTrack();
- default:
- UNREACHABLE();
- }
- return Handle<Code>::null();
-}
-
-// static
-int ConstructorBuiltinsAssembler::FastCloneShallowObjectPropertiesCount(
- int literal_length) {
- // This heuristic of setting empty literals to have
- // kInitialGlobalObjectUnusedPropertiesCount must remain in-sync with the
- // runtime.
- // TODO(verwaest): Unify this with the heuristic in the runtime.
- return literal_length == 0
- ? JSObject::kInitialGlobalObjectUnusedPropertiesCount
- : literal_length;
-}
-
-Node* ConstructorBuiltinsAssembler::EmitFastCloneShallowObject(
- CodeAssemblerLabel* call_runtime, Node* closure, Node* literals_index,
- Node* properties_count) {
- Node* cell = LoadObjectField(closure, JSFunction::kFeedbackVectorOffset);
- Node* feedback_vector = LoadObjectField(cell, Cell::kValueOffset);
- Node* allocation_site = LoadFixedArrayElement(
- feedback_vector, literals_index, 0, CodeStubAssembler::SMI_PARAMETERS);
- GotoIf(IsUndefined(allocation_site), call_runtime);
-
- // Calculate the object and allocation size based on the properties count.
- Node* object_size = IntPtrAdd(WordShl(properties_count, kPointerSizeLog2),
- IntPtrConstant(JSObject::kHeaderSize));
- Node* allocation_size = object_size;
- if (FLAG_allocation_site_pretenuring) {
- allocation_size =
- IntPtrAdd(object_size, IntPtrConstant(AllocationMemento::kSize));
- }
- Node* boilerplate =
- LoadObjectField(allocation_site, AllocationSite::kTransitionInfoOffset);
- Node* boilerplate_map = LoadMap(boilerplate);
- Node* instance_size = LoadMapInstanceSize(boilerplate_map);
- Node* size_in_words = WordShr(object_size, kPointerSizeLog2);
- GotoIfNot(WordEqual(instance_size, size_in_words), call_runtime);
-
- Node* copy = AllocateInNewSpace(allocation_size);
-
- // Copy boilerplate elements.
- Variable offset(this, MachineType::PointerRepresentation());
- offset.Bind(IntPtrConstant(-kHeapObjectTag));
- Node* end_offset = IntPtrAdd(object_size, offset.value());
- Label loop_body(this, &offset), loop_check(this, &offset);
- // We should always have an object size greater than zero.
- Goto(&loop_body);
- Bind(&loop_body);
- {
- // The Allocate above guarantees that the copy lies in new space. This
- // allows us to skip write barriers. This is necessary since we may also be
- // copying unboxed doubles.
- Node* field = Load(MachineType::IntPtr(), boilerplate, offset.value());
- StoreNoWriteBarrier(MachineType::PointerRepresentation(), copy,
- offset.value(), field);
- Goto(&loop_check);
- }
- Bind(&loop_check);
- {
- offset.Bind(IntPtrAdd(offset.value(), IntPtrConstant(kPointerSize)));
- GotoIfNot(IntPtrGreaterThanOrEqual(offset.value(), end_offset), &loop_body);
- }
-
- if (FLAG_allocation_site_pretenuring) {
- Node* memento = InnerAllocate(copy, object_size);
- StoreMapNoWriteBarrier(memento, Heap::kAllocationMementoMapRootIndex);
- StoreObjectFieldNoWriteBarrier(
- memento, AllocationMemento::kAllocationSiteOffset, allocation_site);
- Node* memento_create_count = LoadObjectField(
- allocation_site, AllocationSite::kPretenureCreateCountOffset);
- memento_create_count =
- SmiAdd(memento_create_count, SmiConstant(Smi::FromInt(1)));
- StoreObjectFieldNoWriteBarrier(allocation_site,
- AllocationSite::kPretenureCreateCountOffset,
- memento_create_count);
- }
-
- // TODO(verwaest): Allocate and fill in double boxes.
- return copy;
-}
-
-void ConstructorBuiltinsAssembler::CreateFastCloneShallowObjectBuiltin(
- int properties_count) {
- DCHECK_GE(properties_count, 0);
- DCHECK_LE(properties_count, kMaximumClonedShallowObjectProperties);
- Label call_runtime(this);
- Node* closure = Parameter(0);
- Node* literals_index = Parameter(1);
-
- Node* properties_count_node =
- IntPtrConstant(FastCloneShallowObjectPropertiesCount(properties_count));
- Node* copy = EmitFastCloneShallowObject(
- &call_runtime, closure, literals_index, properties_count_node);
- Return(copy);
-
- Bind(&call_runtime);
- Node* constant_properties = Parameter(2);
- Node* flags = Parameter(3);
- Node* context = Parameter(4);
- TailCallRuntime(Runtime::kCreateObjectLiteral, context, closure,
- literals_index, constant_properties, flags);
-}
-
-#define SHALLOW_OBJECT_BUILTIN(props) \
- TF_BUILTIN(FastCloneShallowObject##props, ConstructorBuiltinsAssembler) { \
- CreateFastCloneShallowObjectBuiltin(props); \
- }
-
-SHALLOW_OBJECT_BUILTIN(0);
-SHALLOW_OBJECT_BUILTIN(1);
-SHALLOW_OBJECT_BUILTIN(2);
-SHALLOW_OBJECT_BUILTIN(3);
-SHALLOW_OBJECT_BUILTIN(4);
-SHALLOW_OBJECT_BUILTIN(5);
-SHALLOW_OBJECT_BUILTIN(6);
-
-Handle<Code> Builtins::NewCloneShallowObject(int length) {
- switch (length) {
- case 0:
- return FastCloneShallowObject0();
- case 1:
- return FastCloneShallowObject1();
- case 2:
- return FastCloneShallowObject2();
- case 3:
- return FastCloneShallowObject3();
- case 4:
- return FastCloneShallowObject4();
- case 5:
- return FastCloneShallowObject5();
- case 6:
- return FastCloneShallowObject6();
- default:
- UNREACHABLE();
- }
- return Handle<Code>::null();
-}
-
-} // namespace internal
-} // namespace v8
« no previous file with comments | « src/builtins/builtins-constructor.h ('k') | src/builtins/builtins-constructor-gen.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698