Commit 9320f3a1 authored by Shiyu Zhang's avatar Shiyu Zhang Committed by Commit Bot

Port ToString to Torque

Change-Id: I9480650b23da4f5aa38a0634c1a7662bf88189d7
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1551407Reviewed-by: 's avatarGeorg Neis <neis@chromium.org>
Reviewed-by: 's avatarMichael Starzinger <mstarzinger@chromium.org>
Reviewed-by: 's avatarJakob Gruber <jgruber@chromium.org>
Reviewed-by: 's avatarTobias Tebbi <tebbi@chromium.org>
Commit-Queue: Shiyu Zhang <shiyu.zhang@intel.com>
Cr-Commit-Position: refs/heads/master@{#60952}
parent e79197b8
......@@ -811,6 +811,8 @@ const kProxyHandlerOrTargetRevoked: constexpr MessageTemplate
generates 'MessageTemplate::kProxyHandlerOrTargetRevoked';
const kConstructorNotFunction: constexpr MessageTemplate
generates 'MessageTemplate::kConstructorNotFunction';
const kSymbolToString: constexpr MessageTemplate
generates 'MessageTemplate::kSymbolToString';
const kMaxArrayIndex:
constexpr uint32 generates 'JSArray::kMaxArrayIndex';
......@@ -1138,7 +1140,12 @@ extern macro ToObject_Inline(Context, Object): JSReceiver;
extern macro IsNullOrUndefined(Object): bool;
extern macro IsTheHole(Object): bool;
extern macro IsString(HeapObject): bool;
extern builtin ToString(Context, Object): String;
transitioning builtin ToString(context: Context, o: Object): String {
return ToStringImpl(context, o);
}
extern transitioning runtime ToStringRT(Context, Object): String;
extern transitioning builtin NonPrimitiveToPrimitive_String(
Context, Object): Object;
extern transitioning runtime NormalizeElements(Context, JSObject);
extern transitioning runtime TransitionElementsKindWithKind(
......@@ -1521,6 +1528,18 @@ Cast<String>(o: HeapObject): String
return HeapObjectToString(o) otherwise CastError;
}
Cast<Oddball>(o: HeapObject): Oddball
labels CastError {
if (IsOddball(o)) return %RawDownCast<Oddball>(o);
goto CastError;
}
Cast<Symbol>(o: HeapObject): Symbol
labels CastError {
if (IsSymbol(o)) return %RawDownCast<Symbol>(o);
goto CastError;
}
Cast<DirectString>(o: HeapObject): DirectString
labels CastError {
return TaggedToDirectString(o) otherwise CastError;
......@@ -2283,6 +2302,8 @@ extern macro IsHeapNumber(HeapObject): bool;
extern macro IsFixedArray(HeapObject): bool;
extern macro IsNumber(Object): bool;
extern macro IsNumberNormalized(Number): bool;
extern macro IsOddball(HeapObject): bool;
extern macro IsSymbol(HeapObject): bool;
extern macro IsJSArrayMap(Map): bool;
extern macro IsExtensibleMap(Map): bool;
extern macro IsCustomElementsReceiverInstanceType(int32): bool;
......@@ -2455,3 +2476,31 @@ transitioning builtin FastCreateDataProperty(implicit context: Context)(
}
return Undefined;
}
transitioning macro ToStringImpl(context: Context, o: Object): String {
let result: Object = o;
while (true) {
typeswitch (result) {
case (str: String): {
return str;
}
case (num: Number): {
return NumberToString(num);
}
case (oddball: Oddball): {
return oddball.to_string;
}
case (Symbol): {
ThrowTypeError(kSymbolToString);
}
case (JSReceiver): {
result = NonPrimitiveToPrimitive_String(context, result);
continue;
}
case (Object): {
return ToStringRT(context, o);
}
}
}
return ToStringRT(context, o);
}
......@@ -131,7 +131,7 @@ TF_BUILTIN(ToName, CodeStubAssembler) {
{
// We don't have a fast-path for BigInt currently, so just
// tail call to the %ToString runtime function here for now.
TailCallRuntime(Runtime::kToString, context, input);
TailCallRuntime(Runtime::kToStringRT, context, input);
}
BIND(&if_inputisname);
......@@ -211,14 +211,6 @@ TF_BUILTIN(NumberToString, CodeStubAssembler) {
Return(NumberToString(input));
}
// ES section #sec-tostring
TF_BUILTIN(ToString, CodeStubAssembler) {
Node* context = Parameter(Descriptor::kContext);
Node* input = Parameter(Descriptor::kArgument);
Return(ToString(context, input));
}
// 7.1.1.1 OrdinaryToPrimitive ( O, hint )
void ConversionBuiltinsAssembler::Generate_OrdinaryToPrimitive(
Node* context, Node* input, OrdinaryToPrimitiveHint hint) {
......
......@@ -202,7 +202,6 @@ namespace internal {
TFC(ToNumberConvertBigInt, TypeConversion) \
TFC(ToNumeric, TypeConversion) \
TFC(NumberToString, TypeConversion) \
TFC(ToString, TypeConversion) \
TFC(ToInteger, TypeConversion) \
TFC(ToInteger_TruncateMinusZero, TypeConversion) \
TFC(ToLength, TypeConversion) \
......
......@@ -302,7 +302,8 @@ TF_BUILTIN(StringAdd_ConvertLeft, StringBuiltinsAssembler) {
Node* context = Parameter(Descriptor::kContext);
// TODO(danno): The ToString and JSReceiverToPrimitive below could be
// combined to avoid duplicate smi and instance type checks.
left = ToString(context, JSReceiverToPrimitive(context, left));
left =
ToStringImpl(CAST(context), CAST(JSReceiverToPrimitive(context, left)));
TailCallBuiltin(Builtins::kStringAdd_CheckNone, context, left, right);
}
......@@ -312,7 +313,8 @@ TF_BUILTIN(StringAdd_ConvertRight, StringBuiltinsAssembler) {
Node* context = Parameter(Descriptor::kContext);
// TODO(danno): The ToString and JSReceiverToPrimitive below could be
// combined to avoid duplicate smi and instance type checks.
right = ToString(context, JSReceiverToPrimitive(context, right));
right =
ToStringImpl(CAST(context), CAST(JSReceiverToPrimitive(context, right)));
TailCallBuiltin(Builtins::kStringAdd_CheckNone, context, left, right);
}
......
......@@ -7818,71 +7818,6 @@ TNode<Number> CodeStubAssembler::ToUint32(SloppyTNode<Context> context,
return CAST(var_result.value());
}
TNode<String> CodeStubAssembler::ToString(SloppyTNode<Context> context,
SloppyTNode<Object> input) {
TVARIABLE(Object, result, input);
Label loop(this, &result), done(this);
Goto(&loop);
BIND(&loop);
{
// Load the current {input} value.
TNode<Object> input = result.value();
// Dispatch based on the type of the {input.}
Label if_inputisnumber(this), if_inputisoddball(this),
if_inputissymbol(this), if_inputisreceiver(this, Label::kDeferred),
runtime(this, Label::kDeferred);
GotoIf(TaggedIsSmi(input), &if_inputisnumber);
TNode<Int32T> input_instance_type = LoadInstanceType(CAST(input));
GotoIf(IsStringInstanceType(input_instance_type), &done);
GotoIf(IsJSReceiverInstanceType(input_instance_type), &if_inputisreceiver);
GotoIf(IsHeapNumberInstanceType(input_instance_type), &if_inputisnumber);
GotoIf(IsOddballInstanceType(input_instance_type), &if_inputisoddball);
Branch(IsSymbolInstanceType(input_instance_type), &if_inputissymbol,
&runtime);
BIND(&if_inputisnumber);
{
// Convert the Number {input} to a String.
TNode<Number> number_input = CAST(input);
result = NumberToString(number_input);
Goto(&done);
}
BIND(&if_inputisoddball);
{
// Just return the {input}'s string representation.
result = LoadObjectField(CAST(input), Oddball::kToStringOffset);
Goto(&done);
}
BIND(&if_inputissymbol);
{
// Throw a type error when {input} is a Symbol.
ThrowTypeError(context, MessageTemplate::kSymbolToString);
}
BIND(&if_inputisreceiver);
{
// Convert the JSReceiver {input} to a primitive first,
// and then run the loop again with the new {input},
// which is then a primitive value.
result = CallBuiltin(Builtins::kNonPrimitiveToPrimitive_String, context,
input);
Goto(&loop);
}
BIND(&runtime);
{
result = CallRuntime(Runtime::kToString, context, input);
Goto(&done);
}
}
BIND(&done);
return CAST(result.value());
}
TNode<String> CodeStubAssembler::ToString_Inline(SloppyTNode<Context> context,
SloppyTNode<Object> input) {
VARIABLE(var_result, MachineRepresentation::kTagged, input);
......
......@@ -2399,8 +2399,6 @@ class V8_EXPORT_PRIVATE CodeStubAssembler
SloppyTNode<Object> input);
// Convert any object to a String.
TNode<String> ToString(SloppyTNode<Context> context,
SloppyTNode<Object> input);
TNode<String> ToString_Inline(SloppyTNode<Context> context,
SloppyTNode<Object> input);
......
......@@ -72,7 +72,7 @@ Reduction JSIntrinsicLowering::Reduce(Node* node) {
return ReduceToLength(node);
case Runtime::kInlineToObject:
return ReduceToObject(node);
case Runtime::kInlineToString:
case Runtime::kInlineToStringRT:
return ReduceToString(node);
case Runtime::kInlineCall:
return ReduceCall(node);
......
......@@ -1816,7 +1816,7 @@ Type Typer::Visitor::TypeJSCallRuntime(Node* node) {
return TypeUnaryOp(node, ToNumber);
case Runtime::kInlineToObject:
return TypeUnaryOp(node, ToObject);
case Runtime::kInlineToString:
case Runtime::kInlineToStringRT:
return TypeUnaryOp(node, ToString);
case Runtime::kHasInPrototypeChain:
return Type::Boolean();
......
......@@ -248,7 +248,7 @@ bool IntrinsicHasNoSideEffect(Runtime::FunctionId id) {
V(ToLength) \
V(ToNumber) \
V(ToObject) \
V(ToString) \
V(ToStringRT) \
/* Type checks */ \
V(IsArray) \
V(IsFunction) \
......
......@@ -207,7 +207,7 @@ Node* IntrinsicsGenerator::HasProperty(
args, context, Builtins::CallableFor(isolate(), Builtins::kHasProperty));
}
Node* IntrinsicsGenerator::ToString(
Node* IntrinsicsGenerator::ToStringRT(
const InterpreterAssembler::RegListNodePair& args, Node* context) {
return IntrinsicAsStubCall(
args, context, Builtins::CallableFor(isolate(), Builtins::kToString));
......
......@@ -36,7 +36,7 @@ namespace interpreter {
V(IsJSReceiver, is_js_receiver, 1) \
V(IsSmi, is_smi, 1) \
V(IsTypedArray, is_typed_array, 1) \
V(ToString, to_string, 1) \
V(ToStringRT, to_string, 1) \
V(ToLength, to_length, 1) \
V(ToObject, to_object, 1)
......
......@@ -631,7 +631,7 @@ class V8_EXPORT_PRIVATE Parser : public NON_EXPORTED_BASE(ParserBase<Parser>) {
if (expr->IsStringLiteral()) return expr;
ScopedPtrList<Expression> args(pointer_buffer());
args.Add(expr);
return factory()->NewCallRuntime(Runtime::kInlineToString, args,
return factory()->NewCallRuntime(Runtime::kInlineToStringRT, args,
expr->position());
}
......
......@@ -1045,15 +1045,13 @@ RUNTIME_FUNCTION(Runtime_ToLength) {
RETURN_RESULT_OR_FAILURE(isolate, Object::ToLength(isolate, input));
}
RUNTIME_FUNCTION(Runtime_ToString) {
RUNTIME_FUNCTION(Runtime_ToStringRT) {
HandleScope scope(isolate);
DCHECK_EQ(1, args.length());
CONVERT_ARG_HANDLE_CHECKED(Object, input, 0);
RETURN_RESULT_OR_FAILURE(isolate, Object::ToString(isolate, input));
}
RUNTIME_FUNCTION(Runtime_ToName) {
HandleScope scope(isolate);
DCHECK_EQ(1, args.length());
......
......@@ -326,7 +326,7 @@ namespace internal {
I(ToNumber, 1, 1) \
F(ToNumeric, 1, 1) \
I(ToObject, 1, 1) \
I(ToString, 1, 1) \
I(ToStringRT, 1, 1) \
F(TryMigrateInstance, 1, 1)
#define FOR_EACH_INTRINSIC_OPERATORS(F, I) \
......
......@@ -85,9 +85,8 @@ void ImplementationVisitor::BeginNamespaceFile(Namespace* nspace) {
<< "\n";
header << "class ";
if (nspace->IsTestNamespace()) {
header << "V8_EXPORT_PRIVATE ";
}
// TODO(sigurds): Decide which assemblers we should export for testing.
header << "V8_EXPORT_PRIVATE ";
header << nspace->ExternalName() << " {\n";
header << " public:\n";
header << " explicit " << nspace->ExternalName()
......
......@@ -367,7 +367,8 @@ TEST(ToString) {
const int kNumParams = 1;
CodeAssemblerTester asm_tester(isolate, kNumParams);
CodeStubAssembler m(asm_tester.state());
m.Return(m.ToString(m.Parameter(kNumParams + 2), m.Parameter(0)));
m.Return(m.ToStringImpl(m.CAST(m.Parameter(kNumParams + 2)),
m.CAST(m.Parameter(0))));
FunctionTester ft(asm_tester.GenerateCode(), kNumParams);
......
......@@ -4,51 +4,51 @@
// Flags: --allow-natives-syntax
assertEquals("1", %ToString(1));
assertEquals("1", %_ToString(1));
assertEquals("1", %ToStringRT(1));
assertEquals("1", %_ToStringRT(1));
assertEquals("0.5", %ToString(.5));
assertEquals("0.5", %_ToString(.5));
assertEquals("0.5", %ToStringRT(.5));
assertEquals("0.5", %_ToStringRT(.5));
assertEquals("null", %ToString(null));
assertEquals("null", %_ToString(null));
assertEquals("null", %ToStringRT(null));
assertEquals("null", %_ToStringRT(null));
assertEquals("true", %ToString(true));
assertEquals("true", %_ToString(true));
assertEquals("true", %ToStringRT(true));
assertEquals("true", %_ToStringRT(true));
assertEquals("false", %ToString(false));
assertEquals("false", %_ToString(false));
assertEquals("false", %ToStringRT(false));
assertEquals("false", %_ToStringRT(false));
assertEquals("undefined", %ToString(undefined));
assertEquals("undefined", %_ToString(undefined));
assertEquals("undefined", %ToStringRT(undefined));
assertEquals("undefined", %_ToStringRT(undefined));
assertEquals("random text", %ToString("random text"));
assertEquals("random text", %_ToString("random text"));
assertEquals("random text", %ToStringRT("random text"));
assertEquals("random text", %_ToStringRT("random text"));
assertThrows(function() { %ToString(Symbol.toPrimitive) }, TypeError);
assertThrows(function() { %_ToString(Symbol.toPrimitive) }, TypeError);
assertThrows(function() { %ToStringRT(Symbol.toPrimitive) }, TypeError);
assertThrows(function() { %_ToStringRT(Symbol.toPrimitive) }, TypeError);
var a = { toString: function() { return "xyz" }};
assertEquals("xyz", %ToString(a));
assertEquals("xyz", %_ToString(a));
assertEquals("xyz", %ToStringRT(a));
assertEquals("xyz", %_ToStringRT(a));
var b = { valueOf: function() { return 42 }};
assertEquals("[object Object]", %ToString(b));
assertEquals("[object Object]", %_ToString(b));
assertEquals("[object Object]", %ToStringRT(b));
assertEquals("[object Object]", %_ToStringRT(b));
var c = {
toString: function() { return "x"},
valueOf: function() { return 123 }
};
assertEquals("x", %ToString(c));
assertEquals("x", %_ToString(c));
assertEquals("x", %ToStringRT(c));
assertEquals("x", %_ToStringRT(c));
var d = {
[Symbol.toPrimitive]: function(hint) { return hint }
};
assertEquals("string", %ToString(d));
assertEquals("string", %_ToString(d));
assertEquals("string", %ToStringRT(d));
assertEquals("string", %_ToStringRT(d));
var e = new Date(0);
assertEquals(e.toString(), %ToString(e));
assertEquals(e.toString(), %_ToString(e));
assertEquals(e.toString(), %ToStringRT(e));
assertEquals(e.toString(), %_ToStringRT(e));
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