Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(52)

Unified Diff: src/builtins/builtins.cc

Issue 2152693002: [stubs] Introduce NonPrimitiveToPrimitive builtin. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Address comments. Created 4 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/builtins/builtins.h ('k') | src/code-factory.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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);
}
« no previous file with comments | « src/builtins/builtins.h ('k') | src/code-factory.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698