summaryrefslogtreecommitdiff
path: root/deps/v8/src/code-stubs.cc
diff options
context:
space:
mode:
Diffstat (limited to 'deps/v8/src/code-stubs.cc')
-rw-r--r--deps/v8/src/code-stubs.cc407
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),
- &dividend_is_not_number);
+ assembler->GotoIfNot(assembler->IsHeapNumberMap(dividend_map),
+ &dividend_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),
- &dividend_is_not_number);
+ assembler->GotoIfNot(assembler->IsHeapNumberMap(dividend_map),
+ &dividend_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;
}