diff options
Diffstat (limited to 'deps/v8/src/code-stubs.cc')
-rw-r--r-- | deps/v8/src/code-stubs.cc | 407 |
1 files changed, 257 insertions, 150 deletions
diff --git a/deps/v8/src/code-stubs.cc b/deps/v8/src/code-stubs.cc index cdaa4ec14f..48d24f8cc3 100644 --- a/deps/v8/src/code-stubs.cc +++ b/deps/v8/src/code-stubs.cc @@ -6,17 +6,19 @@ #include <sstream> +#include "src/arguments.h" #include "src/ast/ast.h" #include "src/bootstrapper.h" #include "src/code-factory.h" #include "src/code-stub-assembler.h" +#include "src/counters.h" #include "src/factory.h" #include "src/gdb-jit.h" -#include "src/ic/accessor-assembler.h" -#include "src/ic/handler-compiler.h" +#include "src/heap/heap-inl.h" #include "src/ic/ic-stats.h" #include "src/ic/ic.h" #include "src/macro-assembler.h" +#include "src/objects-inl.h" #include "src/tracing/tracing-category-observer.h" namespace v8 { @@ -73,7 +75,7 @@ void CodeStubDescriptor::Initialize(Register stack_parameter_count, bool CodeStub::FindCodeInCache(Code** code_out) { UnseededNumberDictionary* stubs = isolate()->heap()->code_stubs(); - int index = stubs->FindEntry(GetKey()); + int index = stubs->FindEntry(isolate(), GetKey()); if (index != UnseededNumberDictionary::kNotFound) { *code_out = Code::cast(stubs->ValueAt(index)); return true; @@ -105,8 +107,7 @@ Code::Flags CodeStub::GetCodeFlags() const { return Code::ComputeFlags(GetCodeKind(), GetExtraICState()); } - -Handle<Code> CodeStub::GetCodeCopy(const Code::FindAndReplacePattern& pattern) { +Handle<Code> CodeStub::GetCodeCopy(const FindAndReplacePattern& pattern) { Handle<Code> ic = GetCode(); ic = isolate()->factory()->CopyCode(ic); ic->FindAndReplace(pattern); @@ -439,11 +440,6 @@ Handle<Code> TurboFanCodeStub::GenerateCode() { return compiler::CodeAssembler::GenerateCode(&state); } -void LoadICProtoArrayStub::GenerateAssembly(CodeAssemblerState* state) const { - AccessorAssembler::GenerateLoadICProtoArray( - state, throw_reference_error_if_nonexistent()); -} - void ElementsTransitionAndStoreStub::GenerateAssembly( compiler::CodeAssemblerState* state) const { typedef CodeStubAssembler::Label Label; @@ -494,21 +490,6 @@ void AllocateHeapNumberStub::GenerateAssembly( assembler.Return(result); } -#define SIMD128_GEN_ASM(TYPE, Type, type, lane_count, lane_type) \ - void Allocate##Type##Stub::GenerateAssembly( \ - compiler::CodeAssemblerState* state) const { \ - CodeStubAssembler assembler(state); \ - compiler::Node* result = \ - assembler.Allocate(Simd128Value::kSize, CodeStubAssembler::kNone); \ - compiler::Node* map = assembler.LoadMap(result); \ - assembler.StoreNoWriteBarrier( \ - MachineRepresentation::kTagged, map, \ - assembler.HeapConstant(isolate()->factory()->type##_map())); \ - assembler.Return(result); \ - } -SIMD128_TYPES(SIMD128_GEN_ASM) -#undef SIMD128_GEN_ASM - void StringLengthStub::GenerateAssembly( compiler::CodeAssemblerState* state) const { CodeStubAssembler assembler(state); @@ -603,8 +584,8 @@ compiler::Node* AddWithFeedbackStub::Generate(CodeStubAssembler* assembler, Node* rhs_map = assembler->LoadMap(rhs); // Check if the {rhs} is a HeapNumber. - assembler->GotoUnless(assembler->IsHeapNumberMap(rhs_map), - &check_rhsisoddball); + assembler->GotoIfNot(assembler->IsHeapNumberMap(rhs_map), + &check_rhsisoddball); var_fadd_lhs.Bind(assembler->SmiToFloat64(lhs)); var_fadd_rhs.Bind(assembler->LoadHeapNumberValue(rhs)); @@ -618,8 +599,8 @@ compiler::Node* AddWithFeedbackStub::Generate(CodeStubAssembler* assembler, Node* lhs_map = assembler->LoadMap(lhs); // Check if {lhs} is a HeapNumber. - assembler->GotoUnless(assembler->IsHeapNumberMap(lhs_map), - &if_lhsisnotnumber); + assembler->GotoIfNot(assembler->IsHeapNumberMap(lhs_map), + &if_lhsisnotnumber); // Check if the {rhs} is Smi. Label if_rhsissmi(assembler), if_rhsisnotsmi(assembler); @@ -639,8 +620,8 @@ compiler::Node* AddWithFeedbackStub::Generate(CodeStubAssembler* assembler, Node* rhs_map = assembler->LoadMap(rhs); // Check if the {rhs} is a HeapNumber. - assembler->GotoUnless(assembler->IsHeapNumberMap(rhs_map), - &check_rhsisoddball); + assembler->GotoIfNot(assembler->IsHeapNumberMap(rhs_map), + &check_rhsisoddball); var_fadd_lhs.Bind(assembler->LoadHeapNumberValue(lhs)); var_fadd_rhs.Bind(assembler->LoadHeapNumberValue(rhs)); @@ -684,8 +665,8 @@ compiler::Node* AddWithFeedbackStub::Generate(CodeStubAssembler* assembler, assembler->Bind(&if_lhsisnotoddball); { // Exit unless {lhs} is a string - assembler->GotoUnless(assembler->IsStringInstanceType(lhs_instance_type), - &call_with_any_feedback); + assembler->GotoIfNot(assembler->IsStringInstanceType(lhs_instance_type), + &call_with_any_feedback); // Check if the {rhs} is a smi, and exit the string check early if it is. assembler->GotoIf(assembler->TaggedIsSmi(rhs), &call_with_any_feedback); @@ -694,8 +675,8 @@ compiler::Node* AddWithFeedbackStub::Generate(CodeStubAssembler* assembler, // Exit unless {rhs} is a string. Since {lhs} is a string we no longer // need an Oddball check. - assembler->GotoUnless(assembler->IsStringInstanceType(rhs_instance_type), - &call_with_any_feedback); + assembler->GotoIfNot(assembler->IsStringInstanceType(rhs_instance_type), + &call_with_any_feedback); var_type_feedback.Bind( assembler->SmiConstant(BinaryOperationFeedback::kString)); @@ -810,8 +791,8 @@ compiler::Node* SubtractWithFeedbackStub::Generate( Node* rhs_map = assembler->LoadMap(rhs); // Check if {rhs} is a HeapNumber. - assembler->GotoUnless(assembler->IsHeapNumberMap(rhs_map), - &check_rhsisoddball); + assembler->GotoIfNot(assembler->IsHeapNumberMap(rhs_map), + &check_rhsisoddball); // Perform a floating point subtraction. var_fsub_lhs.Bind(assembler->SmiToFloat64(lhs)); @@ -826,8 +807,8 @@ compiler::Node* SubtractWithFeedbackStub::Generate( Node* lhs_map = assembler->LoadMap(lhs); // Check if the {lhs} is a HeapNumber. - assembler->GotoUnless(assembler->IsHeapNumberMap(lhs_map), - &if_lhsisnotnumber); + assembler->GotoIfNot(assembler->IsHeapNumberMap(lhs_map), + &if_lhsisnotnumber); // Check if the {rhs} is a Smi. Label if_rhsissmi(assembler), if_rhsisnotsmi(assembler); @@ -848,8 +829,8 @@ compiler::Node* SubtractWithFeedbackStub::Generate( Node* rhs_map = assembler->LoadMap(rhs); // Check if the {rhs} is a HeapNumber. - assembler->GotoUnless(assembler->IsHeapNumberMap(rhs_map), - &check_rhsisoddball); + assembler->GotoIfNot(assembler->IsHeapNumberMap(rhs_map), + &check_rhsisoddball); // Perform a floating point subtraction. var_fsub_lhs.Bind(assembler->LoadHeapNumberValue(lhs)); @@ -876,7 +857,7 @@ compiler::Node* SubtractWithFeedbackStub::Generate( Node* lhs_instance_type = assembler->LoadInstanceType(lhs); Node* lhs_is_oddball = assembler->Word32Equal( lhs_instance_type, assembler->Int32Constant(ODDBALL_TYPE)); - assembler->GotoUnless(lhs_is_oddball, &call_with_any_feedback); + assembler->GotoIfNot(lhs_is_oddball, &call_with_any_feedback); Label if_rhsissmi(assembler), if_rhsisnotsmi(assembler); assembler->Branch(assembler->TaggedIsSmi(rhs), &if_rhsissmi, @@ -895,8 +876,8 @@ compiler::Node* SubtractWithFeedbackStub::Generate( Node* rhs_map = assembler->LoadMap(rhs); // Check if {rhs} is a HeapNumber. - assembler->GotoUnless(assembler->IsHeapNumberMap(rhs_map), - &check_rhsisoddball); + assembler->GotoIfNot(assembler->IsHeapNumberMap(rhs_map), + &check_rhsisoddball); var_type_feedback.Bind( assembler->SmiConstant(BinaryOperationFeedback::kNumberOrOddball)); @@ -911,7 +892,7 @@ compiler::Node* SubtractWithFeedbackStub::Generate( Node* rhs_instance_type = assembler->LoadInstanceType(rhs); Node* rhs_is_oddball = assembler->Word32Equal( rhs_instance_type, assembler->Int32Constant(ODDBALL_TYPE)); - assembler->GotoUnless(rhs_is_oddball, &call_with_any_feedback); + assembler->GotoIfNot(rhs_is_oddball, &call_with_any_feedback); var_type_feedback.Bind( assembler->SmiConstant(BinaryOperationFeedback::kNumberOrOddball)); @@ -984,8 +965,8 @@ compiler::Node* MultiplyWithFeedbackStub::Generate( Node* rhs_map = assembler->LoadMap(rhs); // Check if {rhs} is a HeapNumber. - assembler->GotoUnless(assembler->IsHeapNumberMap(rhs_map), - &check_rhsisoddball); + assembler->GotoIfNot(assembler->IsHeapNumberMap(rhs_map), + &check_rhsisoddball); // Convert {lhs} to a double and multiply it with the value of {rhs}. var_lhs_float64.Bind(assembler->SmiToFloat64(lhs)); @@ -999,8 +980,8 @@ compiler::Node* MultiplyWithFeedbackStub::Generate( Node* lhs_map = assembler->LoadMap(lhs); // Check if {lhs} is a HeapNumber. - assembler->GotoUnless(assembler->IsHeapNumberMap(lhs_map), - &if_lhsisnotnumber); + assembler->GotoIfNot(assembler->IsHeapNumberMap(lhs_map), + &if_lhsisnotnumber); // Check if {rhs} is a Smi. Label rhs_is_smi(assembler), rhs_is_not_smi(assembler); @@ -1020,8 +1001,8 @@ compiler::Node* MultiplyWithFeedbackStub::Generate( Node* rhs_map = assembler->LoadMap(rhs); // Check if {rhs} is a HeapNumber. - assembler->GotoUnless(assembler->IsHeapNumberMap(rhs_map), - &check_rhsisoddball); + assembler->GotoIfNot(assembler->IsHeapNumberMap(rhs_map), + &check_rhsisoddball); // Both {lhs} and {rhs} are HeapNumbers. Load their values and // multiply them. @@ -1049,7 +1030,7 @@ compiler::Node* MultiplyWithFeedbackStub::Generate( Node* lhs_instance_type = assembler->LoadInstanceType(lhs); Node* lhs_is_oddball = assembler->Word32Equal( lhs_instance_type, assembler->Int32Constant(ODDBALL_TYPE)); - assembler->GotoUnless(lhs_is_oddball, &call_with_any_feedback); + assembler->GotoIfNot(lhs_is_oddball, &call_with_any_feedback); assembler->GotoIf(assembler->TaggedIsSmi(rhs), &call_with_oddball_feedback); @@ -1202,8 +1183,8 @@ compiler::Node* DivideWithFeedbackStub::Generate( Node* divisor_map = assembler->LoadMap(divisor); // Check if {divisor} is a HeapNumber. - assembler->GotoUnless(assembler->IsHeapNumberMap(divisor_map), - &check_divisor_for_oddball); + assembler->GotoIfNot(assembler->IsHeapNumberMap(divisor_map), + &check_divisor_for_oddball); // Convert {dividend} to a double and divide it with the value of // {divisor}. @@ -1217,8 +1198,8 @@ compiler::Node* DivideWithFeedbackStub::Generate( Node* dividend_map = assembler->LoadMap(dividend); // Check if {dividend} is a HeapNumber. - assembler->GotoUnless(assembler->IsHeapNumberMap(dividend_map), - ÷nd_is_not_number); + assembler->GotoIfNot(assembler->IsHeapNumberMap(dividend_map), + ÷nd_is_not_number); // Check if {divisor} is a Smi. Label divisor_is_smi(assembler), divisor_is_not_smi(assembler); @@ -1239,8 +1220,8 @@ compiler::Node* DivideWithFeedbackStub::Generate( Node* divisor_map = assembler->LoadMap(divisor); // Check if {divisor} is a HeapNumber. - assembler->GotoUnless(assembler->IsHeapNumberMap(divisor_map), - &check_divisor_for_oddball); + assembler->GotoIfNot(assembler->IsHeapNumberMap(divisor_map), + &check_divisor_for_oddball); // Both {dividend} and {divisor} are HeapNumbers. Load their values // and divide them. @@ -1268,7 +1249,7 @@ compiler::Node* DivideWithFeedbackStub::Generate( Node* dividend_instance_type = assembler->LoadInstanceType(dividend); Node* dividend_is_oddball = assembler->Word32Equal( dividend_instance_type, assembler->Int32Constant(ODDBALL_TYPE)); - assembler->GotoUnless(dividend_is_oddball, &call_with_any_feedback); + assembler->GotoIfNot(dividend_is_oddball, &call_with_any_feedback); assembler->GotoIf(assembler->TaggedIsSmi(divisor), &call_with_oddball_feedback); @@ -1363,8 +1344,8 @@ compiler::Node* ModulusWithFeedbackStub::Generate( Node* divisor_map = assembler->LoadMap(divisor); // Check if {divisor} is a HeapNumber. - assembler->GotoUnless(assembler->IsHeapNumberMap(divisor_map), - &check_divisor_for_oddball); + assembler->GotoIfNot(assembler->IsHeapNumberMap(divisor_map), + &check_divisor_for_oddball); // Convert {dividend} to a double and divide it with the value of // {divisor}. @@ -1379,8 +1360,8 @@ compiler::Node* ModulusWithFeedbackStub::Generate( Node* dividend_map = assembler->LoadMap(dividend); // Check if {dividend} is a HeapNumber. - assembler->GotoUnless(assembler->IsHeapNumberMap(dividend_map), - ÷nd_is_not_number); + assembler->GotoIfNot(assembler->IsHeapNumberMap(dividend_map), + ÷nd_is_not_number); // Check if {divisor} is a Smi. Label divisor_is_smi(assembler), divisor_is_not_smi(assembler); @@ -1401,8 +1382,8 @@ compiler::Node* ModulusWithFeedbackStub::Generate( Node* divisor_map = assembler->LoadMap(divisor); // Check if {divisor} is a HeapNumber. - assembler->GotoUnless(assembler->IsHeapNumberMap(divisor_map), - &check_divisor_for_oddball); + assembler->GotoIfNot(assembler->IsHeapNumberMap(divisor_map), + &check_divisor_for_oddball); // Both {dividend} and {divisor} are HeapNumbers. Load their values // and divide them. @@ -1429,7 +1410,7 @@ compiler::Node* ModulusWithFeedbackStub::Generate( Node* dividend_instance_type = assembler->LoadInstanceType(dividend); Node* dividend_is_oddball = assembler->Word32Equal( dividend_instance_type, assembler->Int32Constant(ODDBALL_TYPE)); - assembler->GotoUnless(dividend_is_oddball, &call_with_any_feedback); + assembler->GotoIfNot(dividend_is_oddball, &call_with_any_feedback); assembler->GotoIf(assembler->TaggedIsSmi(divisor), &call_with_oddball_feedback); @@ -1508,23 +1489,6 @@ void SubStringStub::GenerateAssembly( assembler.Parameter(Descriptor::kContext))); } -void LoadApiGetterStub::GenerateAssembly( - compiler::CodeAssemblerState* state) const { - typedef compiler::Node Node; - CodeStubAssembler assembler(state); - Node* context = assembler.Parameter(Descriptor::kContext); - Node* receiver = assembler.Parameter(Descriptor::kReceiver); - // For now we only support receiver_is_holder. - DCHECK(receiver_is_holder()); - Node* holder = receiver; - Node* map = assembler.LoadMap(receiver); - Node* descriptors = assembler.LoadMapDescriptors(map); - Node* callback = assembler.LoadFixedArrayElement( - descriptors, DescriptorArray::ToValueIndex(index())); - assembler.TailCallStub(CodeFactory::ApiGetter(isolate()), context, receiver, - holder, callback); -} - void StoreGlobalStub::GenerateAssembly( compiler::CodeAssemblerState* state) const { typedef CodeStubAssembler::Label Label; @@ -1584,7 +1548,7 @@ void StoreGlobalStub::GenerateAssembly( if (cell_type == PropertyCellType::kConstantType) { switch (constant_type()) { case PropertyCellConstantType::kSmi: - assembler.GotoUnless(assembler.TaggedIsSmi(value), &miss); + assembler.GotoIfNot(assembler.TaggedIsSmi(value), &miss); value_is_smi = true; break; case PropertyCellConstantType::kStableMap: { @@ -1620,11 +1584,6 @@ void StoreGlobalStub::GenerateAssembly( } } -void LoadFieldStub::GenerateAssembly( - compiler::CodeAssemblerState* state) const { - AccessorAssembler::GenerateLoadField(state); -} - void KeyedLoadSloppyArgumentsStub::GenerateAssembly( compiler::CodeAssemblerState* state) const { typedef CodeStubAssembler::Label Label; @@ -1716,9 +1675,11 @@ void StoreInterceptorStub::GenerateAssembly( Node* receiver = assembler.Parameter(Descriptor::kReceiver); Node* name = assembler.Parameter(Descriptor::kName); Node* value = assembler.Parameter(Descriptor::kValue); + Node* slot = assembler.Parameter(Descriptor::kSlot); + Node* vector = assembler.Parameter(Descriptor::kVector); Node* context = assembler.Parameter(Descriptor::kContext); assembler.TailCallRuntime(Runtime::kStorePropertyWithInterceptor, context, - receiver, name, value); + value, slot, vector, receiver, name); } void LoadIndexedInterceptorStub::GenerateAssembly( @@ -1745,59 +1706,207 @@ void LoadIndexedInterceptorStub::GenerateAssembly( slot, vector); } -template<class StateType> -void HydrogenCodeStub::TraceTransition(StateType from, StateType to) { - // Note: Although a no-op transition is semantically OK, it is hinting at a - // bug somewhere in our state transition machinery. - DCHECK(from != to); - if (V8_LIKELY(!FLAG_ic_stats)) return; - if (FLAG_ic_stats & - v8::tracing::TracingCategoryObserver::ENABLED_BY_TRACING) { - auto ic_stats = ICStats::instance(); - ic_stats->Begin(); - ICInfo& ic_info = ic_stats->Current(); - ic_info.type = MajorName(MajorKey()); - ic_info.state = ToString(from); - ic_info.state += "=>"; - ic_info.state += ToString(to); - ic_stats->End(); - return; - } - OFStream os(stdout); - os << "["; - PrintBaseName(os); - os << ": " << from << "=>" << to << "]" << std::endl; -} - void CallICStub::PrintState(std::ostream& os) const { // NOLINT - os << state(); + os << convert_mode() << ", " << tail_call_mode(); } +void CallICStub::GenerateAssembly(compiler::CodeAssemblerState* state) const { + typedef CodeStubAssembler::Label Label; + typedef compiler::Node Node; + CodeStubAssembler assembler(state); -void JSEntryStub::FinishCode(Handle<Code> code) { - Handle<FixedArray> handler_table = - code->GetIsolate()->factory()->NewFixedArray(1, TENURED); - handler_table->set(0, Smi::FromInt(handler_offset_)); - code->set_handler_table(*handler_table); -} + Node* context = assembler.Parameter(Descriptor::kContext); + Node* target = assembler.Parameter(Descriptor::kTarget); + Node* argc = assembler.Parameter(Descriptor::kActualArgumentsCount); + Node* slot = assembler.Parameter(Descriptor::kSlot); + Node* vector = assembler.Parameter(Descriptor::kVector); + + // TODO(bmeurer): The slot should actually be an IntPtr, but TurboFan's + // SimplifiedLowering cannot deal with IntPtr machine type properly yet. + slot = assembler.ChangeInt32ToIntPtr(slot); + + // Static checks to assert it is safe to examine the type feedback element. + // We don't know that we have a weak cell. We might have a private symbol + // or an AllocationSite, but the memory is safe to examine. + // AllocationSite::kTransitionInfoOffset - contains a Smi or pointer to + // FixedArray. + // WeakCell::kValueOffset - contains a JSFunction or Smi(0) + // Symbol::kHashFieldSlot - if the low bit is 1, then the hash is not + // computed, meaning that it can't appear to be a pointer. If the low bit is + // 0, then hash is computed, but the 0 bit prevents the field from appearing + // to be a pointer. + STATIC_ASSERT(WeakCell::kSize >= kPointerSize); + STATIC_ASSERT(AllocationSite::kTransitionInfoOffset == + WeakCell::kValueOffset && + WeakCell::kValueOffset == Symbol::kHashFieldSlot); + + // Increment the call count. + // TODO(bmeurer): Would it be beneficial to use Int32Add on 64-bit? + assembler.Comment("increment call count"); + Node* call_count = + assembler.LoadFixedArrayElement(vector, slot, 1 * kPointerSize); + Node* new_count = assembler.SmiAdd(call_count, assembler.SmiConstant(1)); + // Count is Smi, so we don't need a write barrier. + assembler.StoreFixedArrayElement(vector, slot, new_count, SKIP_WRITE_BARRIER, + 1 * kPointerSize); + + Label call_function(&assembler), extra_checks(&assembler), call(&assembler); + + // The checks. First, does function match the recorded monomorphic target? + Node* feedback_element = assembler.LoadFixedArrayElement(vector, slot); + Node* feedback_value = assembler.LoadWeakCellValueUnchecked(feedback_element); + Node* is_monomorphic = assembler.WordEqual(target, feedback_value); + assembler.GotoIfNot(is_monomorphic, &extra_checks); + + // The compare above could have been a SMI/SMI comparison. Guard against + // this convincing us that we have a monomorphic JSFunction. + Node* is_smi = assembler.TaggedIsSmi(target); + assembler.Branch(is_smi, &extra_checks, &call_function); + + assembler.Bind(&call_function); + { + // Call using CallFunction builtin. + Callable callable = + CodeFactory::CallFunction(isolate(), convert_mode(), tail_call_mode()); + assembler.TailCallStub(callable, context, target, argc); + } + + assembler.Bind(&extra_checks); + { + Label check_initialized(&assembler), mark_megamorphic(&assembler), + create_allocation_site(&assembler, Label::kDeferred), + create_weak_cell(&assembler, Label::kDeferred); + + assembler.Comment("check if megamorphic"); + // Check if it is a megamorphic target. + Node* is_megamorphic = assembler.WordEqual( + feedback_element, + assembler.HeapConstant(FeedbackVector::MegamorphicSentinel(isolate()))); + assembler.GotoIf(is_megamorphic, &call); + + assembler.Comment("check if it is an allocation site"); + assembler.GotoIfNot( + assembler.IsAllocationSiteMap(assembler.LoadMap(feedback_element)), + &check_initialized); + + // If it is not the Array() function, mark megamorphic. + Node* context_slot = assembler.LoadContextElement( + assembler.LoadNativeContext(context), Context::ARRAY_FUNCTION_INDEX); + Node* is_array_function = assembler.WordEqual(context_slot, target); + assembler.GotoIfNot(is_array_function, &mark_megamorphic); + + // Call ArrayConstructorStub. + Callable callable = CodeFactory::ArrayConstructor(isolate()); + assembler.TailCallStub(callable, context, target, target, argc, + feedback_element); + + assembler.Bind(&check_initialized); + { + assembler.Comment("check if uninitialized"); + // Check if it is uninitialized target first. + Node* is_uninitialized = assembler.WordEqual( + feedback_element, + assembler.HeapConstant( + FeedbackVector::UninitializedSentinel(isolate()))); + assembler.GotoIfNot(is_uninitialized, &mark_megamorphic); + + assembler.Comment("handle unitinitialized"); + // If it is not a JSFunction mark it as megamorphic. + Node* is_smi = assembler.TaggedIsSmi(target); + assembler.GotoIf(is_smi, &mark_megamorphic); + + // Check if function is an object of JSFunction type. + Node* is_js_function = assembler.IsJSFunction(target); + assembler.GotoIfNot(is_js_function, &mark_megamorphic); + + // Check if it is the Array() function. + Node* context_slot = assembler.LoadContextElement( + assembler.LoadNativeContext(context), Context::ARRAY_FUNCTION_INDEX); + Node* is_array_function = assembler.WordEqual(context_slot, target); + assembler.GotoIf(is_array_function, &create_allocation_site); + + // Check if the function belongs to the same native context. + Node* native_context = assembler.LoadNativeContext( + assembler.LoadObjectField(target, JSFunction::kContextOffset)); + Node* is_same_native_context = assembler.WordEqual( + native_context, assembler.LoadNativeContext(context)); + assembler.Branch(is_same_native_context, &create_weak_cell, + &mark_megamorphic); + } + assembler.Bind(&create_weak_cell); + { + // Wrap the {target} in a WeakCell and remember it. + assembler.Comment("create weak cell"); + assembler.CreateWeakCellInFeedbackVector(vector, assembler.SmiTag(slot), + target); -void HandlerStub::InitializeDescriptor(CodeStubDescriptor* descriptor) { - DCHECK(kind() == Code::LOAD_IC || kind() == Code::KEYED_LOAD_IC); - if (kind() == Code::KEYED_LOAD_IC) { - descriptor->Initialize( - FUNCTION_ADDR(Runtime_KeyedLoadIC_MissFromStubFailure)); + // Call using CallFunction builtin. + assembler.Goto(&call_function); + } + + assembler.Bind(&create_allocation_site); + { + // Create an AllocationSite for the {target}. + assembler.Comment("create allocation site"); + assembler.CreateAllocationSiteInFeedbackVector(vector, + assembler.SmiTag(slot)); + + // Call using CallFunction builtin. CallICs have a PREMONOMORPHIC state. + // They start collecting feedback only when a call is executed the second + // time. So, do not pass any feedback here. + assembler.Goto(&call_function); + } + + assembler.Bind(&mark_megamorphic); + { + // Mark it as a megamorphic. + // MegamorphicSentinel is created as a part of Heap::InitialObjects + // and will not move during a GC. So it is safe to skip write barrier. + DCHECK(Heap::RootIsImmortalImmovable(Heap::kmegamorphic_symbolRootIndex)); + assembler.StoreFixedArrayElement( + vector, slot, assembler.HeapConstant( + FeedbackVector::MegamorphicSentinel(isolate())), + SKIP_WRITE_BARRIER); + assembler.Goto(&call); + } + } + + assembler.Bind(&call); + { + // Call using call builtin. + assembler.Comment("call using Call builtin"); + Callable callable_call = + CodeFactory::Call(isolate(), convert_mode(), tail_call_mode()); + assembler.TailCallStub(callable_call, context, target, argc); } } +void CallICTrampolineStub::PrintState(std::ostream& os) const { // NOLINT + os << convert_mode() << ", " << tail_call_mode(); +} -CallInterfaceDescriptor HandlerStub::GetCallInterfaceDescriptor() const { - if (kind() == Code::LOAD_IC || kind() == Code::KEYED_LOAD_IC) { - return LoadWithVectorDescriptor(isolate()); - } else { - DCHECK(kind() == Code::STORE_IC || kind() == Code::KEYED_STORE_IC); - return StoreWithVectorDescriptor(isolate()); - } +void CallICTrampolineStub::GenerateAssembly( + compiler::CodeAssemblerState* state) const { + typedef compiler::Node Node; + CodeStubAssembler assembler(state); + + Node* context = assembler.Parameter(Descriptor::kContext); + Node* target = assembler.Parameter(Descriptor::kTarget); + Node* argc = assembler.Parameter(Descriptor::kActualArgumentsCount); + Node* slot = assembler.Parameter(Descriptor::kSlot); + Node* vector = assembler.LoadFeedbackVectorForStub(); + + Callable callable = + CodeFactory::CallIC(isolate(), convert_mode(), tail_call_mode()); + assembler.TailCallStub(callable, context, target, argc, slot, vector); +} + +void JSEntryStub::FinishCode(Handle<Code> code) { + Handle<FixedArray> handler_table = + code->GetIsolate()->factory()->NewFixedArray(1, TENURED); + handler_table->set(0, Smi::FromInt(handler_offset_)); + code->set_handler_table(*handler_table); } void TransitionElementsKindStub::InitializeDescriptor( @@ -1814,15 +1923,6 @@ void AllocateHeapNumberStub::InitializeDescriptor( } -#define SIMD128_INIT_DESC(TYPE, Type, type, lane_count, lane_type) \ - void Allocate##Type##Stub::InitializeDescriptor( \ - CodeStubDescriptor* descriptor) { \ - descriptor->Initialize( \ - Runtime::FunctionForId(Runtime::kCreate##Type)->entry); \ - } -SIMD128_TYPES(SIMD128_INIT_DESC) -#undef SIMD128_INIT_DESC - void ToBooleanICStub::InitializeDescriptor(CodeStubDescriptor* descriptor) { descriptor->Initialize(FUNCTION_ADDR(Runtime_ToBooleanIC_Miss)); descriptor->SetMissHandler(Runtime::kToBooleanIC_Miss); @@ -1874,7 +1974,7 @@ void GetPropertyStub::GenerateAssembly( }; CodeStubAssembler::LookupInHolder lookup_element_in_holder = - [&assembler, context, &var_result, &end]( + [&assembler]( Node* receiver, Node* holder, Node* holder_map, Node* holder_instance_type, Node* index, Label* next_holder, Label* if_bailout) { @@ -1915,10 +2015,20 @@ void CreateWeakCellStub::GenerateAheadOfTime(Isolate* isolate) { stub.GetCode(); } +void StoreSlowElementStub::GenerateAssembly( + compiler::CodeAssemblerState* state) const { + typedef compiler::Node Node; + CodeStubAssembler assembler(state); + + Node* receiver = assembler.Parameter(Descriptor::kReceiver); + Node* name = assembler.Parameter(Descriptor::kName); + Node* value = assembler.Parameter(Descriptor::kValue); + Node* slot = assembler.Parameter(Descriptor::kSlot); + Node* vector = assembler.Parameter(Descriptor::kVector); + Node* context = assembler.Parameter(Descriptor::kContext); -void StoreElementStub::Generate(MacroAssembler* masm) { - DCHECK_EQ(DICTIONARY_ELEMENTS, elements_kind()); - KeyedStoreIC::GenerateSlow(masm); + assembler.TailCallRuntime(Runtime::kKeyedStoreIC_Slow, context, value, slot, + vector, receiver, name); } void StoreFastElementStub::GenerateAssembly( @@ -1998,15 +2108,12 @@ bool ToBooleanICStub::UpdateStatus(Handle<Object> object) { new_hints |= ToBooleanHint::kHeapNumber; double value = HeapNumber::cast(*object)->value(); to_boolean_value = value != 0 && !std::isnan(value); - } else if (object->IsSimd128Value()) { - new_hints |= ToBooleanHint::kSimdValue; - to_boolean_value = true; } else { // We should never see an internal object at runtime here! UNREACHABLE(); to_boolean_value = true; } - TraceTransition(old_hints, new_hints); + set_sub_minor_key(HintsBits::update(sub_minor_key(), new_hints)); return to_boolean_value; } |