Commit 88531cc7 authored by bmeurer's avatar bmeurer Committed by Commit bot

[stubs] Introduce NonPrimitiveToPrimitive builtin.

This adds initial support for ToPrimitive in JavaScript w/o having to
call out to C++. This uses the newly introduced GetPropertyStub.

R=ishell@chromium.org

Review-Url: https://codereview.chromium.org/2152693002
Cr-Commit-Position: refs/heads/master@{#37753}
parent b34e6ff6
......@@ -5801,6 +5801,30 @@ 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) {
......@@ -6087,6 +6111,166 @@ void Generate_StoreIC_SlowStrict(CodeStubAssembler* assembler) {
Generate_StoreIC_Slow(assembler, STRICT);
}
// 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());
}
void Generate_OrdinaryToPrimitive_Number(CodeStubAssembler* assembler) {
Generate_OrdinaryToPrimitive(assembler, OrdinaryToPrimitiveHint::kNumber);
}
void Generate_OrdinaryToPrimitive_String(CodeStubAssembler* assembler) {
Generate_OrdinaryToPrimitive(assembler, OrdinaryToPrimitiveHint::kString);
}
// 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);
}
}
void Generate_NonPrimitiveToPrimitive_Default(CodeStubAssembler* assembler) {
Generate_NonPrimitiveToPrimitive(assembler, ToPrimitiveHint::kDefault);
}
void Generate_NonPrimitiveToPrimitive_Number(CodeStubAssembler* assembler) {
Generate_NonPrimitiveToPrimitive(assembler, ToPrimitiveHint::kNumber);
}
void Generate_NonPrimitiveToPrimitive_String(CodeStubAssembler* assembler) {
Generate_NonPrimitiveToPrimitive(assembler, ToPrimitiveHint::kString);
}
void Generate_KeyedStoreIC_Slow(MacroAssembler* masm) {
ElementHandlerCompiler::GenerateStoreSlow(masm);
}
......
......@@ -362,17 +362,22 @@ class CodeStubAssembler;
V(AtomicsStore, 4)
// Define list of builtins implemented in TurboFan (with CallStub linkage).
#define BUILTIN_LIST_S(V) \
V(LoadGlobalIC_Miss, BUILTIN, kNoExtraICState, LoadGlobalWithVector) \
V(LoadGlobalIC_SlowNotInsideTypeof, HANDLER, Code::LOAD_GLOBAL_IC, \
LoadGlobalWithVector) \
V(LoadGlobalIC_SlowInsideTypeof, HANDLER, Code::LOAD_GLOBAL_IC, \
LoadGlobalWithVector) \
V(LoadIC_Miss, BUILTIN, kNoExtraICState, LoadWithVector) \
V(LoadIC_Slow, HANDLER, Code::LOAD_IC, LoadWithVector) \
V(StoreIC_Miss, BUILTIN, kNoExtraICState, VectorStoreIC) \
V(StoreIC_SlowSloppy, HANDLER, Code::STORE_IC, VectorStoreIC) \
V(StoreIC_SlowStrict, HANDLER, Code::STORE_IC, VectorStoreIC)
#define BUILTIN_LIST_S(V) \
V(LoadGlobalIC_Miss, BUILTIN, kNoExtraICState, LoadGlobalWithVector) \
V(LoadGlobalIC_SlowNotInsideTypeof, HANDLER, Code::LOAD_GLOBAL_IC, \
LoadGlobalWithVector) \
V(LoadGlobalIC_SlowInsideTypeof, HANDLER, Code::LOAD_GLOBAL_IC, \
LoadGlobalWithVector) \
V(LoadIC_Miss, BUILTIN, kNoExtraICState, LoadWithVector) \
V(LoadIC_Slow, HANDLER, Code::LOAD_IC, LoadWithVector) \
V(StoreIC_Miss, BUILTIN, kNoExtraICState, VectorStoreIC) \
V(StoreIC_SlowSloppy, HANDLER, Code::STORE_IC, VectorStoreIC) \
V(StoreIC_SlowStrict, HANDLER, Code::STORE_IC, VectorStoreIC) \
V(OrdinaryToPrimitive_Number, BUILTIN, kNoExtraICState, TypeConversion) \
V(OrdinaryToPrimitive_String, BUILTIN, kNoExtraICState, TypeConversion) \
V(NonPrimitiveToPrimitive_Default, BUILTIN, kNoExtraICState, TypeConversion) \
V(NonPrimitiveToPrimitive_Number, BUILTIN, kNoExtraICState, TypeConversion) \
V(NonPrimitiveToPrimitive_String, BUILTIN, kNoExtraICState, TypeConversion)
// Define list of builtin handlers implemented in assembly.
#define BUILTIN_LIST_H(V) \
......@@ -457,6 +462,9 @@ class Builtins {
Handle<Code> Call(ConvertReceiverMode = ConvertReceiverMode::kAny,
TailCallMode tail_call_mode = TailCallMode::kDisallow);
Handle<Code> CallBoundFunction(TailCallMode tail_call_mode);
Handle<Code> NonPrimitiveToPrimitive(
ToPrimitiveHint hint = ToPrimitiveHint::kDefault);
Handle<Code> OrdinaryToPrimitive(OrdinaryToPrimitiveHint hint);
Handle<Code> InterpreterPushArgsAndCall(
TailCallMode tail_call_mode,
CallableType function_type = CallableType::kAny);
......
......@@ -137,6 +137,12 @@ Callable CodeFactory::InstanceOf(Isolate* isolate) {
}
// static
Callable CodeFactory::GetProperty(Isolate* isolate) {
GetPropertyStub stub(isolate);
return Callable(stub.GetCode(), stub.GetCallInterfaceDescriptor());
}
// static
Callable CodeFactory::ToBoolean(Isolate* isolate) {
ToBooleanStub stub(isolate);
......@@ -196,6 +202,19 @@ Callable CodeFactory::ToObject(Isolate* isolate) {
return Callable(stub.GetCode(), stub.GetCallInterfaceDescriptor());
}
// static
Callable CodeFactory::NonPrimitiveToPrimitive(Isolate* isolate,
ToPrimitiveHint hint) {
return Callable(isolate->builtins()->NonPrimitiveToPrimitive(hint),
TypeConversionDescriptor(isolate));
}
// static
Callable CodeFactory::OrdinaryToPrimitive(Isolate* isolate,
OrdinaryToPrimitiveHint hint) {
return Callable(isolate->builtins()->OrdinaryToPrimitive(hint),
TypeConversionDescriptor(isolate));
}
// static
Callable CodeFactory::NumberToString(Isolate* isolate) {
......@@ -203,7 +222,6 @@ Callable CodeFactory::NumberToString(Isolate* isolate) {
return Callable(stub.GetCode(), stub.GetCallInterfaceDescriptor());
}
// static
Callable CodeFactory::RegExpConstructResult(Isolate* isolate) {
RegExpConstructResultStub stub(isolate);
......
......@@ -65,6 +65,8 @@ class CodeFactory final {
// code-stubs.h.
static Callable InstanceOf(Isolate* isolate);
static Callable GetProperty(Isolate* isolate);
static Callable ToBoolean(Isolate* isolate);
static Callable ToNumber(Isolate* isolate);
......@@ -75,6 +77,10 @@ class CodeFactory final {
static Callable ToInteger(Isolate* isolate);
static Callable ToLength(Isolate* isolate);
static Callable ToObject(Isolate* isolate);
static Callable NonPrimitiveToPrimitive(
Isolate* isolate, ToPrimitiveHint hint = ToPrimitiveHint::kDefault);
static Callable OrdinaryToPrimitive(Isolate* isolate,
OrdinaryToPrimitiveHint hint);
static Callable NumberToString(Isolate* isolate);
static Callable RegExpConstructResult(Isolate* isolate);
......
......@@ -619,9 +619,9 @@ compiler::Node* AddStub::Generate(CodeStubAssembler* assembler,
assembler->Bind(&if_rhsisreceiver);
{
// Convert {rhs} to a primitive first passing no hint.
// TODO(bmeurer): Hook up ToPrimitiveStub here, once it's there.
var_rhs.Bind(
assembler->CallRuntime(Runtime::kToPrimitive, context, rhs));
Callable callable =
CodeFactory::NonPrimitiveToPrimitive(assembler->isolate());
var_rhs.Bind(assembler->CallStub(callable, context, rhs));
assembler->Goto(&loop);
}
......@@ -697,9 +697,9 @@ compiler::Node* AddStub::Generate(CodeStubAssembler* assembler,
assembler->Bind(&if_lhsisreceiver);
{
// Convert {lhs} to a primitive first passing no hint.
// TODO(bmeurer): Hook up ToPrimitiveStub here, once it's there.
var_lhs.Bind(
assembler->CallRuntime(Runtime::kToPrimitive, context, lhs));
Callable callable =
CodeFactory::NonPrimitiveToPrimitive(assembler->isolate());
var_lhs.Bind(assembler->CallStub(callable, context, lhs));
assembler->Goto(&loop);
}
......@@ -774,9 +774,9 @@ compiler::Node* AddStub::Generate(CodeStubAssembler* assembler,
assembler->Bind(&if_rhsisreceiver);
{
// Convert {rhs} to a primitive first passing no hint.
// TODO(bmeurer): Hook up ToPrimitiveStub here too.
var_rhs.Bind(assembler->CallRuntime(Runtime::kToPrimitive,
context, rhs));
Callable callable = CodeFactory::NonPrimitiveToPrimitive(
assembler->isolate());
var_rhs.Bind(assembler->CallStub(callable, context, rhs));
assembler->Goto(&loop);
}
......@@ -805,9 +805,9 @@ compiler::Node* AddStub::Generate(CodeStubAssembler* assembler,
assembler->Bind(&if_lhsisreceiver);
{
// Convert {lhs} to a primitive first passing no hint.
// TODO(bmeurer): Hook up ToPrimitiveStub here, once it's there.
var_lhs.Bind(assembler->CallRuntime(Runtime::kToPrimitive,
context, lhs));
Callable callable =
CodeFactory::NonPrimitiveToPrimitive(assembler->isolate());
var_lhs.Bind(assembler->CallStub(callable, context, lhs));
assembler->Goto(&loop);
}
......@@ -825,9 +825,9 @@ compiler::Node* AddStub::Generate(CodeStubAssembler* assembler,
assembler->Bind(&if_rhsisreceiver);
{
// Convert {rhs} to a primitive first passing no hint.
// TODO(bmeurer): Hook up ToPrimitiveStub here too.
var_rhs.Bind(assembler->CallRuntime(Runtime::kToPrimitive,
context, rhs));
Callable callable = CodeFactory::NonPrimitiveToPrimitive(
assembler->isolate());
var_rhs.Bind(assembler->CallStub(callable, context, rhs));
assembler->Goto(&loop);
}
......@@ -2211,9 +2211,9 @@ compiler::Node* GenerateAbstractRelationalComparison(
assembler->Bind(&if_rhsisreceiver);
{
// Convert {rhs} to a primitive first passing Number hint.
// TODO(bmeurer): Hook up ToPrimitiveStub here, once it's there.
var_rhs.Bind(assembler->CallRuntime(
Runtime::kToPrimitive_Number, context, rhs));
Callable callable = CodeFactory::NonPrimitiveToPrimitive(
assembler->isolate(), ToPrimitiveHint::kNumber);
var_rhs.Bind(assembler->CallStub(callable, context, rhs));
assembler->Goto(&loop);
}
......@@ -2245,9 +2245,9 @@ compiler::Node* GenerateAbstractRelationalComparison(
assembler->Bind(&if_lhsisreceiver);
{
// Convert {lhs} to a primitive first passing Number hint.
// TODO(bmeurer): Hook up ToPrimitiveStub here, once it's there.
var_lhs.Bind(assembler->CallRuntime(Runtime::kToPrimitive_Number,
context, lhs));
Callable callable = CodeFactory::NonPrimitiveToPrimitive(
assembler->isolate(), ToPrimitiveHint::kNumber);
var_lhs.Bind(assembler->CallStub(callable, context, lhs));
assembler->Goto(&loop);
}
......@@ -2571,9 +2571,9 @@ compiler::Node* GenerateEqual(CodeStubAssembler* assembler, ResultMode mode,
assembler->Bind(&if_rhsisreceiver);
{
// Convert {rhs} to a primitive first (passing no hint).
// TODO(bmeurer): Hook up ToPrimitiveStub here once it exists.
var_rhs.Bind(assembler->CallRuntime(Runtime::kToPrimitive,
context, rhs));
Callable callable = CodeFactory::NonPrimitiveToPrimitive(
assembler->isolate());
var_rhs.Bind(assembler->CallStub(callable, context, rhs));
assembler->Goto(&loop);
}
......@@ -2929,9 +2929,9 @@ compiler::Node* GenerateEqual(CodeStubAssembler* assembler, ResultMode mode,
{
// The {rhs} is some Primitive different from Null and
// Undefined, need to convert {lhs} to Primitive first.
// TODO(bmeurer): Hook up ToPrimitiveStub here once it exists.
var_lhs.Bind(assembler->CallRuntime(Runtime::kToPrimitive,
context, lhs));
Callable callable =
CodeFactory::NonPrimitiveToPrimitive(assembler->isolate());
var_lhs.Bind(assembler->CallStub(callable, context, lhs));
assembler->Goto(&loop);
}
}
......
......@@ -525,6 +525,13 @@ Node* CodeAssembler::CallStubN(const CallInterfaceDescriptor& descriptor,
return CallN(call_descriptor, target, args);
}
Node* CodeAssembler::TailCallStub(Callable const& callable, Node* context,
Node* arg1, size_t result_size) {
Node* target = HeapConstant(callable.code());
return TailCallStub(callable.descriptor(), target, context, arg1,
result_size);
}
Node* CodeAssembler::TailCallStub(Callable const& callable, Node* context,
Node* arg1, Node* arg2, size_t result_size) {
Node* target = HeapConstant(callable.code());
......@@ -540,6 +547,21 @@ Node* CodeAssembler::TailCallStub(Callable const& callable, Node* context,
result_size);
}
Node* CodeAssembler::TailCallStub(const CallInterfaceDescriptor& descriptor,
Node* target, Node* context, Node* arg1,
size_t result_size) {
CallDescriptor* call_descriptor = Linkage::GetStubCallDescriptor(
isolate(), zone(), descriptor, descriptor.GetStackParameterCount(),
CallDescriptor::kSupportsTailCalls, Operator::kNoProperties,
MachineType::AnyTagged(), result_size);
Node** args = zone()->NewArray<Node*>(2);
args[0] = arg1;
args[1] = context;
return raw_assembler_->TailCallN(call_descriptor, target, args);
}
Node* CodeAssembler::TailCallStub(const CallInterfaceDescriptor& descriptor,
Node* target, Node* context, Node* arg1,
Node* arg2, size_t result_size) {
......
......@@ -349,10 +349,14 @@ class CodeAssembler {
Node* CallStubN(const CallInterfaceDescriptor& descriptor, Node* target,
Node** args, size_t result_size = 1);
Node* TailCallStub(Callable const& callable, Node* context, Node* arg1,
size_t result_size = 1);
Node* TailCallStub(Callable const& callable, Node* context, Node* arg1,
Node* arg2, size_t result_size = 1);
Node* TailCallStub(Callable const& callable, Node* context, Node* arg1,
Node* arg2, Node* arg3, size_t result_size = 1);
Node* TailCallStub(const CallInterfaceDescriptor& descriptor, Node* target,
Node* context, Node* arg1, size_t result_size = 1);
Node* TailCallStub(const CallInterfaceDescriptor& descriptor, Node* target,
Node* context, Node* arg1, Node* arg2,
size_t result_size = 1);
......
......@@ -2382,6 +2382,18 @@ Handle<Object> Factory::ToBoolean(bool value) {
return value ? true_value() : false_value();
}
Handle<String> Factory::ToPrimitiveHintString(ToPrimitiveHint hint) {
switch (hint) {
case ToPrimitiveHint::kDefault:
return default_string();
case ToPrimitiveHint::kNumber:
return number_string();
case ToPrimitiveHint::kString:
return string_string();
}
UNREACHABLE();
return Handle<String>::null();
}
} // namespace internal
} // namespace v8
......@@ -684,6 +684,9 @@ class Factory final {
// Converts the given boolean condition to JavaScript boolean value.
Handle<Object> ToBoolean(bool value);
// Converts the given ToPrimitive hint to it's string representation.
Handle<String> ToPrimitiveHintString(ToPrimitiveHint hint);
private:
Isolate* isolate() { return reinterpret_cast<Isolate*>(this); }
......
......@@ -784,6 +784,14 @@ inline std::ostream& operator<<(std::ostream& os, TailCallMode mode) {
return os;
}
// Valid hints for the abstract operation OrdinaryToPrimitive,
// implemented according to ES6, section 7.1.1.
enum class OrdinaryToPrimitiveHint { kNumber, kString };
// Valid hints for the abstract operation ToPrimitive,
// implemented according to ES6, section 7.1.1.
enum class ToPrimitiveHint { kDefault, kNumber, kString };
// Defines specifics about arguments object or rest parameter creation.
enum class CreateArgumentsType : uint8_t {
kMappedArguments,
......
......@@ -8048,18 +8048,8 @@ MaybeHandle<Object> JSReceiver::ToPrimitive(Handle<JSReceiver> receiver,
isolate, exotic_to_prim,
GetMethod(receiver, isolate->factory()->to_primitive_symbol()), Object);
if (!exotic_to_prim->IsUndefined(isolate)) {
Handle<Object> hint_string;
switch (hint) {
case ToPrimitiveHint::kDefault:
hint_string = isolate->factory()->default_string();
break;
case ToPrimitiveHint::kNumber:
hint_string = isolate->factory()->number_string();
break;
case ToPrimitiveHint::kString:
hint_string = isolate->factory()->string_string();
break;
}
Handle<Object> hint_string =
isolate->factory()->ToPrimitiveHintString(hint);
Handle<Object> result;
ASSIGN_RETURN_ON_EXCEPTION(
isolate, result,
......
......@@ -169,16 +169,6 @@ enum KeyedAccessStoreMode {
};
// Valid hints for the abstract operation ToPrimitive,
// implemented according to ES6, section 7.1.1.
enum class ToPrimitiveHint { kDefault, kNumber, kString };
// Valid hints for the abstract operation OrdinaryToPrimitive,
// implemented according to ES6, section 7.1.1.
enum class OrdinaryToPrimitiveHint { kNumber, kString };
enum TypeofMode : int { INSIDE_TYPEOF, NOT_INSIDE_TYPEOF };
......@@ -1845,6 +1835,8 @@ class JSReceiver: public HeapObject {
MUST_USE_RESULT static MaybeHandle<Object> ToPrimitive(
Handle<JSReceiver> receiver,
ToPrimitiveHint hint = ToPrimitiveHint::kDefault);
// ES6 section 7.1.1.1 OrdinaryToPrimitive
MUST_USE_RESULT static MaybeHandle<Object> OrdinaryToPrimitive(
Handle<JSReceiver> receiver, OrdinaryToPrimitiveHint hint);
......
......@@ -207,6 +207,11 @@ RUNTIME_FUNCTION(Runtime_NewSyntaxError) {
return *isolate->factory()->NewSyntaxError(message_template, arg0);
}
RUNTIME_FUNCTION(Runtime_ThrowCannotConvertToPrimitive) {
HandleScope scope(isolate);
THROW_NEW_ERROR_RETURN_FAILURE(
isolate, NewTypeError(MessageTemplate::kCannotConvertToPrimitive));
}
RUNTIME_FUNCTION(Runtime_ThrowIllegalInvocation) {
HandleScope scope(isolate);
......
......@@ -837,7 +837,6 @@ RUNTIME_FUNCTION(Runtime_ToPrimitive_Number) {
isolate, Object::ToPrimitive(input, ToPrimitiveHint::kNumber));
}
RUNTIME_FUNCTION(Runtime_ToNumber) {
HandleScope scope(isolate);
DCHECK_EQ(1, args.length());
......
......@@ -289,6 +289,7 @@ namespace internal {
F(NewTypeError, 2, 1) \
F(NewSyntaxError, 2, 1) \
F(NewReferenceError, 2, 1) \
F(ThrowCannotConvertToPrimitive, 0, 1) \
F(ThrowIllegalInvocation, 0, 1) \
F(ThrowIncompatibleMethodReceiver, 2, 1) \
F(ThrowIteratorResultNotAnObject, 1, 1) \
......
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