| Index: src/builtins/builtins.cc
|
| diff --git a/src/builtins/builtins.cc b/src/builtins/builtins.cc
|
| index 0545c85d6b7cc66339186bb2e839594fdb340d55..9675d0f50402fe3e404aca822df7e52ac0982f42 100644
|
| --- a/src/builtins/builtins.cc
|
| +++ b/src/builtins/builtins.cc
|
| @@ -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);
|
| }
|
|
|