Commit cf259486 authored by yangguo's avatar yangguo Committed by Commit bot

[builtins] move conversions, debugger, handlers, interpreter builtins.

BUG=v8:5197

Review-Url: https://codereview.chromium.org/2168273004
Cr-Commit-Position: refs/heads/master@{#38012}
parent c2d6d983
......@@ -876,12 +876,16 @@ v8_source_set("v8_base") {
"src/builtins/builtins-arraybuffer.cc",
"src/builtins/builtins-boolean.cc",
"src/builtins/builtins-callsite.cc",
"src/builtins/builtins-conversion.cc",
"src/builtins/builtins-dataview.cc",
"src/builtins/builtins-date.cc",
"src/builtins/builtins-debug.cc",
"src/builtins/builtins-error.cc",
"src/builtins/builtins-function.cc",
"src/builtins/builtins-global.cc",
"src/builtins/builtins-handler.cc",
"src/builtins/builtins-internal.cc",
"src/builtins/builtins-interpreter.cc",
"src/builtins/builtins-json.cc",
"src/builtins/builtins-math.cc",
"src/builtins/builtins-number.cc",
......
// 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.h"
#include "src/builtins/builtins-utils.h"
#include "src/code-factory.h"
namespace v8 {
namespace internal {
Handle<Code> Builtins::NonPrimitiveToPrimitive(ToPrimitiveHint hint) {
switch (hint) {
case ToPrimitiveHint::kDefault:
return NonPrimitiveToPrimitive_Default();
case ToPrimitiveHint::kNumber:
return NonPrimitiveToPrimitive_Number();
case ToPrimitiveHint::kString:
return NonPrimitiveToPrimitive_String();
}
UNREACHABLE();
return Handle<Code>::null();
}
namespace {
// ES6 section 7.1.1 ToPrimitive ( input [ , PreferredType ] )
void Generate_NonPrimitiveToPrimitive(CodeStubAssembler* assembler,
ToPrimitiveHint hint) {
typedef CodeStubAssembler::Label Label;
typedef compiler::Node Node;
Node* input = assembler->Parameter(0);
Node* context = assembler->Parameter(1);
// Lookup the @@toPrimitive property on the {input}.
Callable callable = CodeFactory::GetProperty(assembler->isolate());
Node* to_primitive_symbol =
assembler->HeapConstant(assembler->factory()->to_primitive_symbol());
Node* exotic_to_prim =
assembler->CallStub(callable, context, input, to_primitive_symbol);
// Check if {exotic_to_prim} is neither null nor undefined.
Label ordinary_to_primitive(assembler);
assembler->GotoIf(
assembler->WordEqual(exotic_to_prim, assembler->NullConstant()),
&ordinary_to_primitive);
assembler->GotoIf(
assembler->WordEqual(exotic_to_prim, assembler->UndefinedConstant()),
&ordinary_to_primitive);
{
// Invoke the {exotic_to_prim} method on the {input} with a string
// representation of the {hint}.
Callable callable = CodeFactory::Call(assembler->isolate());
Node* hint_string = assembler->HeapConstant(
assembler->factory()->ToPrimitiveHintString(hint));
Node* result = assembler->CallJS(callable, context, exotic_to_prim, input,
hint_string);
// Verify that the {result} is actually a primitive.
Label if_resultisprimitive(assembler),
if_resultisnotprimitive(assembler, Label::kDeferred);
assembler->GotoIf(assembler->WordIsSmi(result), &if_resultisprimitive);
Node* result_instance_type = assembler->LoadInstanceType(result);
STATIC_ASSERT(FIRST_PRIMITIVE_TYPE == FIRST_TYPE);
assembler->Branch(assembler->Int32LessThanOrEqual(
result_instance_type,
assembler->Int32Constant(LAST_PRIMITIVE_TYPE)),
&if_resultisprimitive, &if_resultisnotprimitive);
assembler->Bind(&if_resultisprimitive);
{
// Just return the {result}.
assembler->Return(result);
}
assembler->Bind(&if_resultisnotprimitive);
{
// Somehow the @@toPrimitive method on {input} didn't yield a primitive.
assembler->TailCallRuntime(Runtime::kThrowCannotConvertToPrimitive,
context);
}
}
// Convert using the OrdinaryToPrimitive algorithm instead.
assembler->Bind(&ordinary_to_primitive);
{
Callable callable = CodeFactory::OrdinaryToPrimitive(
assembler->isolate(), (hint == ToPrimitiveHint::kString)
? OrdinaryToPrimitiveHint::kString
: OrdinaryToPrimitiveHint::kNumber);
assembler->TailCallStub(callable, context, input);
}
}
} // anonymous namespace
void Builtins::Generate_NonPrimitiveToPrimitive_Default(
CodeStubAssembler* assembler) {
Generate_NonPrimitiveToPrimitive(assembler, ToPrimitiveHint::kDefault);
}
void Builtins::Generate_NonPrimitiveToPrimitive_Number(
CodeStubAssembler* assembler) {
Generate_NonPrimitiveToPrimitive(assembler, ToPrimitiveHint::kNumber);
}
void Builtins::Generate_NonPrimitiveToPrimitive_String(
CodeStubAssembler* assembler) {
Generate_NonPrimitiveToPrimitive(assembler, ToPrimitiveHint::kString);
}
// ES6 section 7.1.3 ToNumber ( argument )
void Builtins::Generate_NonNumberToNumber(CodeStubAssembler* assembler) {
typedef CodeStubAssembler::Label Label;
typedef compiler::Node Node;
typedef CodeStubAssembler::Variable Variable;
Node* input = assembler->Parameter(0);
Node* context = assembler->Parameter(1);
// We might need to loop once here due to ToPrimitive conversions.
Variable var_input(assembler, MachineRepresentation::kTagged);
Label loop(assembler, &var_input);
var_input.Bind(input);
assembler->Goto(&loop);
assembler->Bind(&loop);
{
// Load the current {input} value (known to be a HeapObject).
Node* input = var_input.value();
// Dispatch on the {input} instance type.
Node* input_instance_type = assembler->LoadInstanceType(input);
Label if_inputisstring(assembler), if_inputisoddball(assembler),
if_inputisreceiver(assembler, Label::kDeferred),
if_inputisother(assembler, Label::kDeferred);
assembler->GotoIf(assembler->Int32LessThan(
input_instance_type,
assembler->Int32Constant(FIRST_NONSTRING_TYPE)),
&if_inputisstring);
assembler->GotoIf(
assembler->Word32Equal(input_instance_type,
assembler->Int32Constant(ODDBALL_TYPE)),
&if_inputisoddball);
STATIC_ASSERT(LAST_JS_RECEIVER_TYPE == LAST_TYPE);
assembler->Branch(assembler->Int32GreaterThanOrEqual(
input_instance_type,
assembler->Int32Constant(FIRST_JS_RECEIVER_TYPE)),
&if_inputisreceiver, &if_inputisother);
assembler->Bind(&if_inputisstring);
{
// The {input} is a String, use the fast stub to convert it to a Number.
// TODO(bmeurer): Consider inlining the StringToNumber logic here.
Callable callable = CodeFactory::StringToNumber(assembler->isolate());
assembler->TailCallStub(callable, context, input);
}
assembler->Bind(&if_inputisoddball);
{
// The {input} is an Oddball, we just need to the Number value of it.
Node* result =
assembler->LoadObjectField(input, Oddball::kToNumberOffset);
assembler->Return(result);
}
assembler->Bind(&if_inputisreceiver);
{
// The {input} is a JSReceiver, we need to convert it to a Primitive first
// using the ToPrimitive type conversion, preferably yielding a Number.
Callable callable = CodeFactory::NonPrimitiveToPrimitive(
assembler->isolate(), ToPrimitiveHint::kNumber);
Node* result = assembler->CallStub(callable, context, input);
// Check if the {result} is already a Number.
Label if_resultisnumber(assembler), if_resultisnotnumber(assembler);
assembler->GotoIf(assembler->WordIsSmi(result), &if_resultisnumber);
Node* result_map = assembler->LoadMap(result);
assembler->Branch(
assembler->WordEqual(result_map, assembler->HeapNumberMapConstant()),
&if_resultisnumber, &if_resultisnotnumber);
assembler->Bind(&if_resultisnumber);
{
// The ToPrimitive conversion already gave us a Number, so we're done.
assembler->Return(result);
}
assembler->Bind(&if_resultisnotnumber);
{
// We now have a Primitive {result}, but it's not yet a Number.
var_input.Bind(result);
assembler->Goto(&loop);
}
}
assembler->Bind(&if_inputisother);
{
// The {input} is something else (i.e. Symbol or Simd128Value), let the
// runtime figure out the correct exception.
// Note: We cannot tail call to the runtime here, as js-to-wasm
// trampolines also use this code currently, and they declare all
// outgoing parameters as untagged, while we would push a tagged
// object here.
Node* result = assembler->CallRuntime(Runtime::kToNumber, context, input);
assembler->Return(result);
}
}
}
Handle<Code> Builtins::OrdinaryToPrimitive(OrdinaryToPrimitiveHint hint) {
switch (hint) {
case OrdinaryToPrimitiveHint::kNumber:
return OrdinaryToPrimitive_Number();
case OrdinaryToPrimitiveHint::kString:
return OrdinaryToPrimitive_String();
}
UNREACHABLE();
return Handle<Code>::null();
}
namespace {
// 7.1.1.1 OrdinaryToPrimitive ( O, hint )
void Generate_OrdinaryToPrimitive(CodeStubAssembler* assembler,
OrdinaryToPrimitiveHint hint) {
typedef CodeStubAssembler::Label Label;
typedef compiler::Node Node;
typedef CodeStubAssembler::Variable Variable;
Node* input = assembler->Parameter(0);
Node* context = assembler->Parameter(1);
Variable var_result(assembler, MachineRepresentation::kTagged);
Label return_result(assembler, &var_result);
Handle<String> method_names[2];
switch (hint) {
case OrdinaryToPrimitiveHint::kNumber:
method_names[0] = assembler->factory()->valueOf_string();
method_names[1] = assembler->factory()->toString_string();
break;
case OrdinaryToPrimitiveHint::kString:
method_names[0] = assembler->factory()->toString_string();
method_names[1] = assembler->factory()->valueOf_string();
break;
}
for (Handle<String> name : method_names) {
// Lookup the {name} on the {input}.
Callable callable = CodeFactory::GetProperty(assembler->isolate());
Node* name_string = assembler->HeapConstant(name);
Node* method = assembler->CallStub(callable, context, input, name_string);
// Check if the {method} is callable.
Label if_methodiscallable(assembler),
if_methodisnotcallable(assembler, Label::kDeferred);
assembler->GotoIf(assembler->WordIsSmi(method), &if_methodisnotcallable);
Node* method_map = assembler->LoadMap(method);
Node* method_bit_field = assembler->LoadMapBitField(method_map);
assembler->Branch(
assembler->Word32Equal(
assembler->Word32And(method_bit_field, assembler->Int32Constant(
1 << Map::kIsCallable)),
assembler->Int32Constant(0)),
&if_methodisnotcallable, &if_methodiscallable);
assembler->Bind(&if_methodiscallable);
{
// Call the {method} on the {input}.
Callable callable = CodeFactory::Call(assembler->isolate());
Node* result = assembler->CallJS(callable, context, method, input);
var_result.Bind(result);
// Return the {result} if it is a primitive.
assembler->GotoIf(assembler->WordIsSmi(result), &return_result);
Node* result_instance_type = assembler->LoadInstanceType(result);
STATIC_ASSERT(FIRST_PRIMITIVE_TYPE == FIRST_TYPE);
assembler->GotoIf(assembler->Int32LessThanOrEqual(
result_instance_type,
assembler->Int32Constant(LAST_PRIMITIVE_TYPE)),
&return_result);
}
// Just continue with the next {name} if the {method} is not callable.
assembler->Goto(&if_methodisnotcallable);
assembler->Bind(&if_methodisnotcallable);
}
assembler->TailCallRuntime(Runtime::kThrowCannotConvertToPrimitive, context);
assembler->Bind(&return_result);
assembler->Return(var_result.value());
}
} // anonymous namespace
void Builtins::Generate_OrdinaryToPrimitive_Number(
CodeStubAssembler* assembler) {
Generate_OrdinaryToPrimitive(assembler, OrdinaryToPrimitiveHint::kNumber);
}
void Builtins::Generate_OrdinaryToPrimitive_String(
CodeStubAssembler* assembler) {
Generate_OrdinaryToPrimitive(assembler, OrdinaryToPrimitiveHint::kString);
}
// ES6 section 7.1.2 ToBoolean ( argument )
void Builtins::Generate_ToBoolean(CodeStubAssembler* assembler) {
typedef compiler::Node Node;
typedef CodeStubAssembler::Label Label;
Node* value = assembler->Parameter(0);
Label return_true(assembler), return_false(assembler);
assembler->BranchIfToBooleanIsTrue(value, &return_true, &return_false);
assembler->Bind(&return_true);
assembler->Return(assembler->BooleanConstant(true));
assembler->Bind(&return_false);
assembler->Return(assembler->BooleanConstant(false));
}
} // namespace internal
} // namespace v8
// 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.h"
#include "src/builtins/builtins-utils.h"
#include "src/debug/debug.h"
namespace v8 {
namespace internal {
void Builtins::Generate_Return_DebugBreak(MacroAssembler* masm) {
DebugCodegen::GenerateDebugBreakStub(masm,
DebugCodegen::SAVE_RESULT_REGISTER);
}
void Builtins::Generate_Slot_DebugBreak(MacroAssembler* masm) {
DebugCodegen::GenerateDebugBreakStub(masm,
DebugCodegen::IGNORE_RESULT_REGISTER);
}
void Builtins::Generate_FrameDropper_LiveEdit(MacroAssembler* masm) {
DebugCodegen::GenerateFrameDropperLiveEdit(masm);
}
} // namespace internal
} // namespace v8
// 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.h"
#include "src/builtins/builtins-utils.h"
#include "src/ic/handler-compiler.h"
#include "src/ic/ic.h"
namespace v8 {
namespace internal {
void Builtins::Generate_KeyedLoadIC_Megamorphic(MacroAssembler* masm) {
KeyedLoadIC::GenerateMegamorphic(masm);
}
void Builtins::Generate_KeyedLoadIC_Miss(MacroAssembler* masm) {
KeyedLoadIC::GenerateMiss(masm);
}
void Builtins::Generate_KeyedLoadIC_Slow(MacroAssembler* masm) {
KeyedLoadIC::GenerateRuntimeGetProperty(masm);
}
void Builtins::Generate_KeyedStoreIC_Megamorphic(MacroAssembler* masm) {
KeyedStoreIC::GenerateMegamorphic(masm, SLOPPY);
}
void Builtins::Generate_KeyedStoreIC_Megamorphic_Strict(MacroAssembler* masm) {
KeyedStoreIC::GenerateMegamorphic(masm, STRICT);
}
void Builtins::Generate_KeyedStoreIC_Miss(MacroAssembler* masm) {
KeyedStoreIC::GenerateMiss(masm);
}
void Builtins::Generate_KeyedStoreIC_Slow(MacroAssembler* masm) {
ElementHandlerCompiler::GenerateStoreSlow(masm);
}
void Builtins::Generate_LoadGlobalIC_Miss(CodeStubAssembler* assembler) {
typedef compiler::Node Node;
Node* slot = assembler->Parameter(0);
Node* vector = assembler->Parameter(1);
Node* context = assembler->Parameter(2);
assembler->TailCallRuntime(Runtime::kLoadGlobalIC_Miss, context, slot,
vector);
}
namespace {
void Generate_LoadGlobalIC_Slow(CodeStubAssembler* assembler, TypeofMode mode) {
typedef compiler::Node Node;
Node* slot = assembler->Parameter(0);
Node* vector = assembler->Parameter(1);
Node* context = assembler->Parameter(2);
Node* typeof_mode = assembler->SmiConstant(Smi::FromInt(mode));
assembler->TailCallRuntime(Runtime::kGetGlobal, context, slot, vector,
typeof_mode);
}
} // anonymous namespace
void Builtins::Generate_LoadGlobalIC_SlowInsideTypeof(
CodeStubAssembler* assembler) {
Generate_LoadGlobalIC_Slow(assembler, INSIDE_TYPEOF);
}
void Builtins::Generate_LoadGlobalIC_SlowNotInsideTypeof(
CodeStubAssembler* assembler) {
Generate_LoadGlobalIC_Slow(assembler, NOT_INSIDE_TYPEOF);
}
void Builtins::Generate_LoadIC_Getter_ForDeopt(MacroAssembler* masm) {
NamedLoadHandlerCompiler::GenerateLoadViaGetterForDeopt(masm);
}
void Builtins::Generate_LoadIC_Miss(CodeStubAssembler* assembler) {
typedef compiler::Node Node;
Node* receiver = assembler->Parameter(0);
Node* name = assembler->Parameter(1);
Node* slot = assembler->Parameter(2);
Node* vector = assembler->Parameter(3);
Node* context = assembler->Parameter(4);
assembler->TailCallRuntime(Runtime::kLoadIC_Miss, context, receiver, name,
slot, vector);
}
void Builtins::Generate_LoadIC_Normal(MacroAssembler* masm) {
LoadIC::GenerateNormal(masm);
}
void Builtins::Generate_LoadIC_Slow(CodeStubAssembler* assembler) {
typedef compiler::Node Node;
Node* receiver = assembler->Parameter(0);
Node* name = assembler->Parameter(1);
// Node* slot = assembler->Parameter(2);
// Node* vector = assembler->Parameter(3);
Node* context = assembler->Parameter(4);
assembler->TailCallRuntime(Runtime::kGetProperty, context, receiver, name);
}
void Builtins::Generate_StoreIC_Miss(CodeStubAssembler* assembler) {
typedef compiler::Node Node;
Node* receiver = assembler->Parameter(0);
Node* name = assembler->Parameter(1);
Node* value = assembler->Parameter(2);
Node* slot = assembler->Parameter(3);
Node* vector = assembler->Parameter(4);
Node* context = assembler->Parameter(5);
assembler->TailCallRuntime(Runtime::kStoreIC_Miss, context, receiver, name,
value, slot, vector);
}
void Builtins::Generate_StoreIC_Normal(MacroAssembler* masm) {
StoreIC::GenerateNormal(masm);
}
void Builtins::Generate_StoreIC_Setter_ForDeopt(MacroAssembler* masm) {
NamedStoreHandlerCompiler::GenerateStoreViaSetterForDeopt(masm);
}
namespace {
void Generate_StoreIC_Slow(CodeStubAssembler* assembler,
LanguageMode language_mode) {
typedef compiler::Node Node;
Node* receiver = assembler->Parameter(0);
Node* name = assembler->Parameter(1);
Node* value = assembler->Parameter(2);
// Node* slot = assembler->Parameter(3);
// Node* vector = assembler->Parameter(4);
Node* context = assembler->Parameter(5);
Node* lang_mode = assembler->SmiConstant(Smi::FromInt(language_mode));
// The slow case calls into the runtime to complete the store without causing
// an IC miss that would otherwise cause a transition to the generic stub.
assembler->TailCallRuntime(Runtime::kSetProperty, context, receiver, name,
value, lang_mode);
}
} // anonymous namespace
void Builtins::Generate_StoreIC_SlowSloppy(CodeStubAssembler* assembler) {
Generate_StoreIC_Slow(assembler, SLOPPY);
}
void Builtins::Generate_StoreIC_SlowStrict(CodeStubAssembler* assembler) {
Generate_StoreIC_Slow(assembler, STRICT);
}
} // namespace internal
} // namespace v8
// 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.h"
#include "src/builtins/builtins-utils.h"
namespace v8 {
namespace internal {
Handle<Code> Builtins::InterpreterPushArgsAndCall(TailCallMode tail_call_mode,
CallableType function_type) {
switch (tail_call_mode) {
case TailCallMode::kDisallow:
if (function_type == CallableType::kJSFunction) {
return InterpreterPushArgsAndCallFunction();
} else {
return InterpreterPushArgsAndCall();
}
case TailCallMode::kAllow:
if (function_type == CallableType::kJSFunction) {
return InterpreterPushArgsAndTailCallFunction();
} else {
return InterpreterPushArgsAndTailCall();
}
}
UNREACHABLE();
return Handle<Code>::null();
}
void Builtins::Generate_InterpreterPushArgsAndCall(MacroAssembler* masm) {
return Generate_InterpreterPushArgsAndCallImpl(masm, TailCallMode::kDisallow,
CallableType::kAny);
}
void Builtins::Generate_InterpreterPushArgsAndCallFunction(
MacroAssembler* masm) {
return Generate_InterpreterPushArgsAndCallImpl(masm, TailCallMode::kDisallow,
CallableType::kJSFunction);
}
void Builtins::Generate_InterpreterPushArgsAndTailCall(MacroAssembler* masm) {
return Generate_InterpreterPushArgsAndCallImpl(masm, TailCallMode::kAllow,
CallableType::kAny);
}
void Builtins::Generate_InterpreterPushArgsAndTailCallFunction(
MacroAssembler* masm) {
return Generate_InterpreterPushArgsAndCallImpl(masm, TailCallMode::kAllow,
CallableType::kJSFunction);
}
} // namespace internal
} // namespace v8
......@@ -339,50 +339,6 @@ Handle<Code> Builtins::CallBoundFunction(TailCallMode tail_call_mode) {
return Handle<Code>::null();
}
Handle<Code> Builtins::NonPrimitiveToPrimitive(ToPrimitiveHint hint) {
switch (hint) {
case ToPrimitiveHint::kDefault:
return NonPrimitiveToPrimitive_Default();
case ToPrimitiveHint::kNumber:
return NonPrimitiveToPrimitive_Number();
case ToPrimitiveHint::kString:
return NonPrimitiveToPrimitive_String();
}
UNREACHABLE();
return Handle<Code>::null();
}
Handle<Code> Builtins::OrdinaryToPrimitive(OrdinaryToPrimitiveHint hint) {
switch (hint) {
case OrdinaryToPrimitiveHint::kNumber:
return OrdinaryToPrimitive_Number();
case OrdinaryToPrimitiveHint::kString:
return OrdinaryToPrimitive_String();
}
UNREACHABLE();
return Handle<Code>::null();
}
Handle<Code> Builtins::InterpreterPushArgsAndCall(TailCallMode tail_call_mode,
CallableType function_type) {
switch (tail_call_mode) {
case TailCallMode::kDisallow:
if (function_type == CallableType::kJSFunction) {
return InterpreterPushArgsAndCallFunction();
} else {
return InterpreterPushArgsAndCall();
}
case TailCallMode::kAllow:
if (function_type == CallableType::kJSFunction) {
return InterpreterPushArgsAndTailCallFunction();
} else {
return InterpreterPushArgsAndTailCall();
}
}
UNREACHABLE();
return Handle<Code>::null();
}
namespace {
class RelocatableArguments : public BuiltinArguments, public Relocatable {
......@@ -527,450 +483,6 @@ BUILTIN(HandleApiCallAsConstructor) {
return HandleApiCallAsFunctionOrConstructor(isolate, true, args);
}
void Builtins::Generate_LoadIC_Miss(CodeStubAssembler* assembler) {
typedef compiler::Node Node;
Node* receiver = assembler->Parameter(0);
Node* name = assembler->Parameter(1);
Node* slot = assembler->Parameter(2);
Node* vector = assembler->Parameter(3);
Node* context = assembler->Parameter(4);
assembler->TailCallRuntime(Runtime::kLoadIC_Miss, context, receiver, name,
slot, vector);
}
void Builtins::Generate_LoadGlobalIC_Miss(CodeStubAssembler* assembler) {
typedef compiler::Node Node;
Node* slot = assembler->Parameter(0);
Node* vector = assembler->Parameter(1);
Node* context = assembler->Parameter(2);
assembler->TailCallRuntime(Runtime::kLoadGlobalIC_Miss, context, slot,
vector);
}
void Builtins::Generate_LoadIC_Normal(MacroAssembler* masm) {
LoadIC::GenerateNormal(masm);
}
void Builtins::Generate_LoadIC_Getter_ForDeopt(MacroAssembler* masm) {
NamedLoadHandlerCompiler::GenerateLoadViaGetterForDeopt(masm);
}
void Builtins::Generate_LoadIC_Slow(CodeStubAssembler* assembler) {
typedef compiler::Node Node;
Node* receiver = assembler->Parameter(0);
Node* name = assembler->Parameter(1);
// Node* slot = assembler->Parameter(2);
// Node* vector = assembler->Parameter(3);
Node* context = assembler->Parameter(4);
assembler->TailCallRuntime(Runtime::kGetProperty, context, receiver, name);
}
namespace {
void Generate_LoadGlobalIC_Slow(CodeStubAssembler* assembler, TypeofMode mode) {
typedef compiler::Node Node;
Node* slot = assembler->Parameter(0);
Node* vector = assembler->Parameter(1);
Node* context = assembler->Parameter(2);
Node* typeof_mode = assembler->SmiConstant(Smi::FromInt(mode));
assembler->TailCallRuntime(Runtime::kGetGlobal, context, slot, vector,
typeof_mode);
}
} // anonymous namespace
void Builtins::Generate_LoadGlobalIC_SlowInsideTypeof(
CodeStubAssembler* assembler) {
Generate_LoadGlobalIC_Slow(assembler, INSIDE_TYPEOF);
}
void Builtins::Generate_LoadGlobalIC_SlowNotInsideTypeof(
CodeStubAssembler* assembler) {
Generate_LoadGlobalIC_Slow(assembler, NOT_INSIDE_TYPEOF);
}
void Builtins::Generate_KeyedLoadIC_Slow(MacroAssembler* masm) {
KeyedLoadIC::GenerateRuntimeGetProperty(masm);
}
void Builtins::Generate_KeyedLoadIC_Miss(MacroAssembler* masm) {
KeyedLoadIC::GenerateMiss(masm);
}
void Builtins::Generate_KeyedLoadIC_Megamorphic(MacroAssembler* masm) {
KeyedLoadIC::GenerateMegamorphic(masm);
}
void Builtins::Generate_StoreIC_Miss(CodeStubAssembler* assembler) {
typedef compiler::Node Node;
Node* receiver = assembler->Parameter(0);
Node* name = assembler->Parameter(1);
Node* value = assembler->Parameter(2);
Node* slot = assembler->Parameter(3);
Node* vector = assembler->Parameter(4);
Node* context = assembler->Parameter(5);
assembler->TailCallRuntime(Runtime::kStoreIC_Miss, context, receiver, name,
value, slot, vector);
}
void Builtins::Generate_StoreIC_Normal(MacroAssembler* masm) {
StoreIC::GenerateNormal(masm);
}
namespace {
void Generate_StoreIC_Slow(CodeStubAssembler* assembler,
LanguageMode language_mode) {
typedef compiler::Node Node;
Node* receiver = assembler->Parameter(0);
Node* name = assembler->Parameter(1);
Node* value = assembler->Parameter(2);
// Node* slot = assembler->Parameter(3);
// Node* vector = assembler->Parameter(4);
Node* context = assembler->Parameter(5);
Node* lang_mode = assembler->SmiConstant(Smi::FromInt(language_mode));
// The slow case calls into the runtime to complete the store without causing
// an IC miss that would otherwise cause a transition to the generic stub.
assembler->TailCallRuntime(Runtime::kSetProperty, context, receiver, name,
value, lang_mode);
}
} // anonymous namespace
void Builtins::Generate_StoreIC_SlowSloppy(CodeStubAssembler* assembler) {
Generate_StoreIC_Slow(assembler, SLOPPY);
}
void Builtins::Generate_StoreIC_SlowStrict(CodeStubAssembler* assembler) {
Generate_StoreIC_Slow(assembler, STRICT);
}
namespace {
// 7.1.1.1 OrdinaryToPrimitive ( O, hint )
void Generate_OrdinaryToPrimitive(CodeStubAssembler* assembler,
OrdinaryToPrimitiveHint hint) {
typedef CodeStubAssembler::Label Label;
typedef compiler::Node Node;
typedef CodeStubAssembler::Variable Variable;
Node* input = assembler->Parameter(0);
Node* context = assembler->Parameter(1);
Variable var_result(assembler, MachineRepresentation::kTagged);
Label return_result(assembler, &var_result);
Handle<String> method_names[2];
switch (hint) {
case OrdinaryToPrimitiveHint::kNumber:
method_names[0] = assembler->factory()->valueOf_string();
method_names[1] = assembler->factory()->toString_string();
break;
case OrdinaryToPrimitiveHint::kString:
method_names[0] = assembler->factory()->toString_string();
method_names[1] = assembler->factory()->valueOf_string();
break;
}
for (Handle<String> name : method_names) {
// Lookup the {name} on the {input}.
Callable callable = CodeFactory::GetProperty(assembler->isolate());
Node* name_string = assembler->HeapConstant(name);
Node* method = assembler->CallStub(callable, context, input, name_string);
// Check if the {method} is callable.
Label if_methodiscallable(assembler),
if_methodisnotcallable(assembler, Label::kDeferred);
assembler->GotoIf(assembler->WordIsSmi(method), &if_methodisnotcallable);
Node* method_map = assembler->LoadMap(method);
Node* method_bit_field = assembler->LoadMapBitField(method_map);
assembler->Branch(
assembler->Word32Equal(
assembler->Word32And(method_bit_field, assembler->Int32Constant(
1 << Map::kIsCallable)),
assembler->Int32Constant(0)),
&if_methodisnotcallable, &if_methodiscallable);
assembler->Bind(&if_methodiscallable);
{
// Call the {method} on the {input}.
Callable callable = CodeFactory::Call(assembler->isolate());
Node* result = assembler->CallJS(callable, context, method, input);
var_result.Bind(result);
// Return the {result} if it is a primitive.
assembler->GotoIf(assembler->WordIsSmi(result), &return_result);
Node* result_instance_type = assembler->LoadInstanceType(result);
STATIC_ASSERT(FIRST_PRIMITIVE_TYPE == FIRST_TYPE);
assembler->GotoIf(assembler->Int32LessThanOrEqual(
result_instance_type,
assembler->Int32Constant(LAST_PRIMITIVE_TYPE)),
&return_result);
}
// Just continue with the next {name} if the {method} is not callable.
assembler->Goto(&if_methodisnotcallable);
assembler->Bind(&if_methodisnotcallable);
}
assembler->TailCallRuntime(Runtime::kThrowCannotConvertToPrimitive, context);
assembler->Bind(&return_result);
assembler->Return(var_result.value());
}
} // anonymous namespace
void Builtins::Generate_OrdinaryToPrimitive_Number(
CodeStubAssembler* assembler) {
Generate_OrdinaryToPrimitive(assembler, OrdinaryToPrimitiveHint::kNumber);
}
void Builtins::Generate_OrdinaryToPrimitive_String(
CodeStubAssembler* assembler) {
Generate_OrdinaryToPrimitive(assembler, OrdinaryToPrimitiveHint::kString);
}
namespace {
// ES6 section 7.1.1 ToPrimitive ( input [ , PreferredType ] )
void Generate_NonPrimitiveToPrimitive(CodeStubAssembler* assembler,
ToPrimitiveHint hint) {
typedef CodeStubAssembler::Label Label;
typedef compiler::Node Node;
Node* input = assembler->Parameter(0);
Node* context = assembler->Parameter(1);
// Lookup the @@toPrimitive property on the {input}.
Callable callable = CodeFactory::GetProperty(assembler->isolate());
Node* to_primitive_symbol =
assembler->HeapConstant(assembler->factory()->to_primitive_symbol());
Node* exotic_to_prim =
assembler->CallStub(callable, context, input, to_primitive_symbol);
// Check if {exotic_to_prim} is neither null nor undefined.
Label ordinary_to_primitive(assembler);
assembler->GotoIf(
assembler->WordEqual(exotic_to_prim, assembler->NullConstant()),
&ordinary_to_primitive);
assembler->GotoIf(
assembler->WordEqual(exotic_to_prim, assembler->UndefinedConstant()),
&ordinary_to_primitive);
{
// Invoke the {exotic_to_prim} method on the {input} with a string
// representation of the {hint}.
Callable callable = CodeFactory::Call(assembler->isolate());
Node* hint_string = assembler->HeapConstant(
assembler->factory()->ToPrimitiveHintString(hint));
Node* result = assembler->CallJS(callable, context, exotic_to_prim, input,
hint_string);
// Verify that the {result} is actually a primitive.
Label if_resultisprimitive(assembler),
if_resultisnotprimitive(assembler, Label::kDeferred);
assembler->GotoIf(assembler->WordIsSmi(result), &if_resultisprimitive);
Node* result_instance_type = assembler->LoadInstanceType(result);
STATIC_ASSERT(FIRST_PRIMITIVE_TYPE == FIRST_TYPE);
assembler->Branch(assembler->Int32LessThanOrEqual(
result_instance_type,
assembler->Int32Constant(LAST_PRIMITIVE_TYPE)),
&if_resultisprimitive, &if_resultisnotprimitive);
assembler->Bind(&if_resultisprimitive);
{
// Just return the {result}.
assembler->Return(result);
}
assembler->Bind(&if_resultisnotprimitive);
{
// Somehow the @@toPrimitive method on {input} didn't yield a primitive.
assembler->TailCallRuntime(Runtime::kThrowCannotConvertToPrimitive,
context);
}
}
// Convert using the OrdinaryToPrimitive algorithm instead.
assembler->Bind(&ordinary_to_primitive);
{
Callable callable = CodeFactory::OrdinaryToPrimitive(
assembler->isolate(), (hint == ToPrimitiveHint::kString)
? OrdinaryToPrimitiveHint::kString
: OrdinaryToPrimitiveHint::kNumber);
assembler->TailCallStub(callable, context, input);
}
}
} // anonymous namespace
void Builtins::Generate_NonPrimitiveToPrimitive_Default(
CodeStubAssembler* assembler) {
Generate_NonPrimitiveToPrimitive(assembler, ToPrimitiveHint::kDefault);
}
void Builtins::Generate_NonPrimitiveToPrimitive_Number(
CodeStubAssembler* assembler) {
Generate_NonPrimitiveToPrimitive(assembler, ToPrimitiveHint::kNumber);
}
void Builtins::Generate_NonPrimitiveToPrimitive_String(
CodeStubAssembler* assembler) {
Generate_NonPrimitiveToPrimitive(assembler, ToPrimitiveHint::kString);
}
// ES6 section 7.1.3 ToNumber ( argument )
void Builtins::Generate_NonNumberToNumber(CodeStubAssembler* assembler) {
typedef CodeStubAssembler::Label Label;
typedef compiler::Node Node;
typedef CodeStubAssembler::Variable Variable;
Node* input = assembler->Parameter(0);
Node* context = assembler->Parameter(1);
// We might need to loop once here due to ToPrimitive conversions.
Variable var_input(assembler, MachineRepresentation::kTagged);
Label loop(assembler, &var_input);
var_input.Bind(input);
assembler->Goto(&loop);
assembler->Bind(&loop);
{
// Load the current {input} value (known to be a HeapObject).
Node* input = var_input.value();
// Dispatch on the {input} instance type.
Node* input_instance_type = assembler->LoadInstanceType(input);
Label if_inputisstring(assembler), if_inputisoddball(assembler),
if_inputisreceiver(assembler, Label::kDeferred),
if_inputisother(assembler, Label::kDeferred);
assembler->GotoIf(assembler->Int32LessThan(
input_instance_type,
assembler->Int32Constant(FIRST_NONSTRING_TYPE)),
&if_inputisstring);
assembler->GotoIf(
assembler->Word32Equal(input_instance_type,
assembler->Int32Constant(ODDBALL_TYPE)),
&if_inputisoddball);
STATIC_ASSERT(LAST_JS_RECEIVER_TYPE == LAST_TYPE);
assembler->Branch(assembler->Int32GreaterThanOrEqual(
input_instance_type,
assembler->Int32Constant(FIRST_JS_RECEIVER_TYPE)),
&if_inputisreceiver, &if_inputisother);
assembler->Bind(&if_inputisstring);
{
// The {input} is a String, use the fast stub to convert it to a Number.
// TODO(bmeurer): Consider inlining the StringToNumber logic here.
Callable callable = CodeFactory::StringToNumber(assembler->isolate());
assembler->TailCallStub(callable, context, input);
}
assembler->Bind(&if_inputisoddball);
{
// The {input} is an Oddball, we just need to the Number value of it.
Node* result =
assembler->LoadObjectField(input, Oddball::kToNumberOffset);
assembler->Return(result);
}
assembler->Bind(&if_inputisreceiver);
{
// The {input} is a JSReceiver, we need to convert it to a Primitive first
// using the ToPrimitive type conversion, preferably yielding a Number.
Callable callable = CodeFactory::NonPrimitiveToPrimitive(
assembler->isolate(), ToPrimitiveHint::kNumber);
Node* result = assembler->CallStub(callable, context, input);
// Check if the {result} is already a Number.
Label if_resultisnumber(assembler), if_resultisnotnumber(assembler);
assembler->GotoIf(assembler->WordIsSmi(result), &if_resultisnumber);
Node* result_map = assembler->LoadMap(result);
assembler->Branch(
assembler->WordEqual(result_map, assembler->HeapNumberMapConstant()),
&if_resultisnumber, &if_resultisnotnumber);
assembler->Bind(&if_resultisnumber);
{
// The ToPrimitive conversion already gave us a Number, so we're done.
assembler->Return(result);
}
assembler->Bind(&if_resultisnotnumber);
{
// We now have a Primitive {result}, but it's not yet a Number.
var_input.Bind(result);
assembler->Goto(&loop);
}
}
assembler->Bind(&if_inputisother);
{
// The {input} is something else (i.e. Symbol or Simd128Value), let the
// runtime figure out the correct exception.
// Note: We cannot tail call to the runtime here, as js-to-wasm
// trampolines also use this code currently, and they declare all
// outgoing parameters as untagged, while we would push a tagged
// object here.
Node* result = assembler->CallRuntime(Runtime::kToNumber, context, input);
assembler->Return(result);
}
}
}
// ES6 section 7.1.2 ToBoolean ( argument )
void Builtins::Generate_ToBoolean(CodeStubAssembler* assembler) {
typedef compiler::Node Node;
typedef CodeStubAssembler::Label Label;
Node* value = assembler->Parameter(0);
Label return_true(assembler), return_false(assembler);
assembler->BranchIfToBooleanIsTrue(value, &return_true, &return_false);
assembler->Bind(&return_true);
assembler->Return(assembler->BooleanConstant(true));
assembler->Bind(&return_false);
assembler->Return(assembler->BooleanConstant(false));
}
void Builtins::Generate_KeyedStoreIC_Slow(MacroAssembler* masm) {
ElementHandlerCompiler::GenerateStoreSlow(masm);
}
void Builtins::Generate_StoreIC_Setter_ForDeopt(MacroAssembler* masm) {
NamedStoreHandlerCompiler::GenerateStoreViaSetterForDeopt(masm);
}
void Builtins::Generate_KeyedStoreIC_Megamorphic(MacroAssembler* masm) {
KeyedStoreIC::GenerateMegamorphic(masm, SLOPPY);
}
void Builtins::Generate_KeyedStoreIC_Megamorphic_Strict(MacroAssembler* masm) {
KeyedStoreIC::GenerateMegamorphic(masm, STRICT);
}
void Builtins::Generate_KeyedStoreIC_Miss(MacroAssembler* masm) {
KeyedStoreIC::GenerateMiss(masm);
}
void Builtins::Generate_Return_DebugBreak(MacroAssembler* masm) {
DebugCodegen::GenerateDebugBreakStub(masm,
DebugCodegen::SAVE_RESULT_REGISTER);
}
void Builtins::Generate_Slot_DebugBreak(MacroAssembler* masm) {
DebugCodegen::GenerateDebugBreakStub(masm,
DebugCodegen::IGNORE_RESULT_REGISTER);
}
void Builtins::Generate_FrameDropper_LiveEdit(MacroAssembler* masm) {
DebugCodegen::GenerateFrameDropperLiveEdit(masm);
}
Builtins::Builtins() : initialized_(false) {
memset(builtins_, 0, sizeof(builtins_[0]) * builtin_count);
}
......@@ -1230,26 +742,6 @@ void Builtins::Generate_TailCall_ReceiverIsAny(MacroAssembler* masm) {
Generate_Call(masm, ConvertReceiverMode::kAny, TailCallMode::kAllow);
}
void Builtins::Generate_InterpreterPushArgsAndCall(MacroAssembler* masm) {
return Generate_InterpreterPushArgsAndCallImpl(masm, TailCallMode::kDisallow,
CallableType::kAny);
}
void Builtins::Generate_InterpreterPushArgsAndTailCall(MacroAssembler* masm) {
return Generate_InterpreterPushArgsAndCallImpl(masm, TailCallMode::kAllow,
CallableType::kAny);
}
void Builtins::Generate_InterpreterPushArgsAndCallFunction(
MacroAssembler* masm) {
return Generate_InterpreterPushArgsAndCallImpl(masm, TailCallMode::kDisallow,
CallableType::kJSFunction);
}
void Builtins::Generate_InterpreterPushArgsAndTailCallFunction(
MacroAssembler* masm) {
return Generate_InterpreterPushArgsAndCallImpl(masm, TailCallMode::kAllow,
CallableType::kJSFunction);
}
#define DEFINE_BUILTIN_ACCESSOR(Name, ...) \
Handle<Code> Builtins::Name() { \
......
......@@ -50,26 +50,26 @@ namespace internal {
#define BUILTIN_LIST(CPP, API, TFJ, TFS, ASM, ASH, DBG) \
ASM(Abort) \
/* Handlers */ \
ASM(KeyedLoadIC_Miss) \
ASM(KeyedStoreIC_Miss) \
ASH(LoadIC_Getter_ForDeopt, LOAD_IC, kNoExtraICState) \
ASH(KeyedLoadIC_Megamorphic, KEYED_LOAD_IC, kNoExtraICState) \
ASH(StoreIC_Setter_ForDeopt, STORE_IC, StoreICState::kStrictModeState) \
ASM(KeyedLoadIC_Miss) \
ASH(KeyedLoadIC_Slow, HANDLER, Code::KEYED_LOAD_IC) \
ASH(KeyedStoreIC_Megamorphic, KEYED_STORE_IC, kNoExtraICState) \
ASH(KeyedStoreIC_Megamorphic_Strict, KEYED_STORE_IC, \
StoreICState::kStrictModeState) \
ASH(KeyedLoadIC_Slow, HANDLER, Code::KEYED_LOAD_IC) \
ASM(KeyedStoreIC_Miss) \
ASH(KeyedStoreIC_Slow, HANDLER, Code::KEYED_STORE_IC) \
ASH(LoadIC_Normal, HANDLER, Code::LOAD_IC) \
ASH(StoreIC_Normal, HANDLER, Code::STORE_IC) \
TFS(LoadGlobalIC_Miss, BUILTIN, kNoExtraICState, LoadGlobalWithVector) \
TFS(LoadGlobalIC_SlowNotInsideTypeof, HANDLER, Code::LOAD_GLOBAL_IC, \
LoadGlobalWithVector) \
TFS(LoadGlobalIC_SlowInsideTypeof, HANDLER, Code::LOAD_GLOBAL_IC, \
LoadGlobalWithVector) \
TFS(LoadGlobalIC_SlowNotInsideTypeof, HANDLER, Code::LOAD_GLOBAL_IC, \
LoadGlobalWithVector) \
ASH(LoadIC_Getter_ForDeopt, LOAD_IC, kNoExtraICState) \
TFS(LoadIC_Miss, BUILTIN, kNoExtraICState, LoadWithVector) \
ASH(LoadIC_Normal, HANDLER, Code::LOAD_IC) \
TFS(LoadIC_Slow, HANDLER, Code::LOAD_IC, LoadWithVector) \
TFS(StoreIC_Miss, BUILTIN, kNoExtraICState, StoreWithVector) \
ASH(StoreIC_Normal, HANDLER, Code::STORE_IC) \
ASH(StoreIC_Setter_ForDeopt, STORE_IC, StoreICState::kStrictModeState) \
TFS(StoreIC_SlowSloppy, HANDLER, Code::STORE_IC, StoreWithVector) \
TFS(StoreIC_SlowStrict, HANDLER, Code::STORE_IC, StoreWithVector) \
\
......@@ -124,11 +124,11 @@ namespace internal {
/* Interpreter */ \
ASM(InterpreterEntryTrampoline) \
ASM(InterpreterMarkBaselineOnReturn) \
ASM(InterpreterPushArgsAndCallFunction) \
ASM(InterpreterPushArgsAndTailCallFunction) \
ASM(InterpreterPushArgsAndCall) \
ASM(InterpreterPushArgsAndTailCall) \
ASM(InterpreterPushArgsAndCallFunction) \
ASM(InterpreterPushArgsAndConstruct) \
ASM(InterpreterPushArgsAndTailCall) \
ASM(InterpreterPushArgsAndTailCallFunction) \
ASM(InterpreterEnterBytecodeDispatch) \
\
/* Code life-cycle */ \
......@@ -159,9 +159,9 @@ namespace internal {
ASM(AllocateInOldSpace) \
\
/* Debugger */ \
DBG(FrameDropper_LiveEdit) \
DBG(Return_DebugBreak) \
DBG(Slot_DebugBreak) \
DBG(FrameDropper_LiveEdit) \
\
/* Type conversions */ \
TFS(ToBoolean, BUILTIN, kNoExtraICState, TypeConversion) \
......
......@@ -489,12 +489,16 @@
'builtins/builtins-array.cc',
'builtins/builtins-boolean.cc',
'builtins/builtins-callsite.cc',
'builtins/builtins-conversion.cc',
'builtins/builtins-dataview.cc',
'builtins/builtins-date.cc',
'builtins/builtins-debug.cc',
'builtins/builtins-error.cc',
'builtins/builtins-function.cc',
'builtins/builtins-global.cc',
'builtins/builtins-handler.cc',
'builtins/builtins-internal.cc',
'builtins/builtins-interpreter.cc',
'builtins/builtins-json.cc',
'builtins/builtins-math.cc',
'builtins/builtins-number.cc',
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment