[stubs] Unify (and optimize) implementation of ToObject.

This is the initial (big) step towards a more uniform implementation of
the ToObject abstract operation (ES6 7.1.13), where we have a fallback
implementation in JSReceiver::ToObject() and a fast (hydrogen) CodeStub
to deal with the fast case (we should be able to do more cleanup on this
in a followup CL).  For natives we expose the abstract operation via a
%_ToObject intrinsic, also exposed via a macro TO_OBJECT, that unifies
the previous confusion with TO_OBJECT_INLINE, ToObject, TO_OBJECT,
$toObject and %$toObject.  Now the whole implementation of the abstract
operation is context independent, meaning we don't need any magic in the
builtins object nor the native context.

R=mvstanton@chromium.org,yangguo@chromium.org

Review URL: https://codereview.chromium.org/1266013006

Cr-Commit-Position: refs/heads/master@{#29953}
This commit is contained in:
bmeurer 2015-07-31 05:25:28 -07:00 committed by Commit bot
parent f8a4afa7bd
commit 4fc6f54724
72 changed files with 560 additions and 198 deletions

View File

@ -6913,7 +6913,7 @@ class Internals {
static const int kJSObjectHeaderSize = 3 * kApiPointerSize;
static const int kFixedArrayHeaderSize = 2 * kApiPointerSize;
static const int kContextHeaderSize = 2 * kApiPointerSize;
static const int kContextEmbedderDataIndex = 82;
static const int kContextEmbedderDataIndex = 81;
static const int kFullStringRepresentationMask = 0x07;
static const int kStringEncodingMask = 0x4;
static const int kExternalTwoByteRepresentationTag = 0x02;

View File

@ -1319,8 +1319,9 @@ void Builtins::Generate_FunctionCall(MacroAssembler* masm) {
__ SmiTag(r0);
__ push(r0);
__ push(r2);
__ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
__ mov(r0, r2);
ToObjectStub stub(masm->isolate());
__ CallStub(&stub);
__ mov(r2, r0);
__ pop(r0);
@ -1556,8 +1557,8 @@ static void Generate_ApplyHelper(MacroAssembler* masm, bool targetIsArgument) {
// Convert the receiver to a regular object.
// r0: receiver
__ bind(&call_to_object);
__ push(r0);
__ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
ToObjectStub stub(masm->isolate());
__ CallStub(&stub);
__ b(&push_receiver);
__ bind(&use_global_proxy);

View File

@ -2547,8 +2547,10 @@ static void EmitSlowCase(MacroAssembler* masm,
static void EmitWrapCase(MacroAssembler* masm, int argc, Label* cont) {
// Wrap the receiver and patch it back onto the stack.
{ FrameAndConstantPoolScope frame_scope(masm, StackFrame::INTERNAL);
__ Push(r1, r3);
__ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
__ push(r1);
__ mov(r0, r3);
ToObjectStub stub(masm->isolate());
__ CallStub(&stub);
__ pop(r1);
}
__ str(r0, MemOperand(sp, argc * kPointerSize));

View File

@ -95,6 +95,10 @@ void ToNumberDescriptor::InitializePlatformSpecific(
}
// static
const Register ToObjectDescriptor::ReceiverRegister() { return r0; }
void NumberToStringDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
Register registers[] = {r0};

View File

@ -1355,8 +1355,10 @@ void Builtins::Generate_FunctionCall(MacroAssembler* masm) {
FrameScope scope(masm, StackFrame::INTERNAL);
__ SmiTag(argc);
__ Push(argc, receiver);
__ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
__ Push(argc);
__ Mov(x0, receiver);
ToObjectStub stub(masm->isolate());
__ CallStub(&stub);
__ Mov(receiver, x0);
__ Pop(argc);
@ -1582,8 +1584,9 @@ static void Generate_ApplyHelper(MacroAssembler* masm, bool targetIsArgument) {
// Call a builtin to convert the receiver to a regular object.
__ Bind(&convert_receiver_to_object);
__ Push(receiver);
__ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
__ Mov(x0, receiver);
ToObjectStub stub(masm->isolate());
__ CallStub(&stub);
__ Mov(receiver, x0);
__ B(&push_receiver);

View File

@ -2921,8 +2921,10 @@ static void EmitSlowCase(MacroAssembler* masm,
static void EmitWrapCase(MacroAssembler* masm, int argc, Label* cont) {
// Wrap the receiver and patch it back onto the stack.
{ FrameScope frame_scope(masm, StackFrame::INTERNAL);
__ Push(x1, x3);
__ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
__ Push(x1);
__ Mov(x0, x3);
ToObjectStub stub(masm->isolate());
__ CallStub(&stub);
__ Pop(x1);
}
__ Poke(x0, argc * kPointerSize);

View File

@ -104,6 +104,10 @@ void ToNumberDescriptor::InitializePlatformSpecific(
}
// static
const Register ToObjectDescriptor::ReceiverRegister() { return x0; }
void NumberToStringDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
// x0: value

View File

@ -45,7 +45,7 @@ function ArrayIterator() {}
// 15.4.5.1 CreateArrayIterator Abstract Operation
function CreateArrayIterator(array, kind) {
var object = $toObject(array);
var object = TO_OBJECT(array);
var iterator = new ArrayIterator;
SET_PRIVATE(iterator, arrayIteratorObjectSymbol, object);
SET_PRIVATE(iterator, arrayIteratorNextIndexSymbol, 0);
@ -68,7 +68,7 @@ function ArrayIteratorIterator() {
// 15.4.5.2.2 ArrayIterator.prototype.next( )
function ArrayIteratorNext() {
var iterator = $toObject(this);
var iterator = TO_OBJECT(this);
if (!HAS_DEFINED_PRIVATE(iterator, arrayIteratorNextIndexSymbol)) {
throw MakeTypeError(kIncompatibleMethodReceiver,

View File

@ -227,7 +227,7 @@ function ConvertToLocaleString(e) {
// According to ES5, section 15.4.4.3, the toLocaleString conversion
// must throw a TypeError if ToObject(e).toLocaleString isn't
// callable.
var e_obj = $toObject(e);
var e_obj = TO_OBJECT(e);
return $toString(e_obj.toLocaleString());
}
}
@ -388,7 +388,7 @@ function ArrayToString() {
}
array = this;
} else {
array = $toObject(this);
array = TO_OBJECT(this);
func = array.join;
}
if (!IS_SPEC_FUNCTION(func)) {
@ -406,7 +406,7 @@ function InnerArrayToLocaleString(array, length) {
function ArrayToLocaleString() {
var array = $toObject(this);
var array = TO_OBJECT(this);
var arrayLen = array.length;
return InnerArrayToLocaleString(array, arrayLen);
}
@ -437,7 +437,7 @@ function InnerArrayJoin(separator, array, length) {
function ArrayJoin(separator) {
CHECK_OBJECT_COERCIBLE(this, "Array.prototype.join");
var array = TO_OBJECT_INLINE(this);
var array = TO_OBJECT(this);
var length = TO_UINT32(array.length);
return InnerArrayJoin(separator, array, length);
@ -466,7 +466,7 @@ function ObservedArrayPop(n) {
function ArrayPop() {
CHECK_OBJECT_COERCIBLE(this, "Array.prototype.pop");
var array = TO_OBJECT_INLINE(this);
var array = TO_OBJECT(this);
var n = TO_UINT32(array.length);
if (n == 0) {
array.length = n;
@ -512,7 +512,7 @@ function ArrayPush() {
if (%IsObserved(this))
return ObservedArrayPush.apply(this, arguments);
var array = TO_OBJECT_INLINE(this);
var array = TO_OBJECT(this);
var n = TO_UINT32(array.length);
var m = %_ArgumentsLength();
@ -532,7 +532,7 @@ function ArrayPush() {
function ArrayConcatJS(arg1) { // length == 1
CHECK_OBJECT_COERCIBLE(this, "Array.prototype.concat");
var array = $toObject(this);
var array = TO_OBJECT(this);
var arg_count = %_ArgumentsLength();
var arrays = new InternalArray(1 + arg_count);
arrays[0] = array;
@ -627,7 +627,7 @@ function GenericArrayReverse(array, len) {
function ArrayReverse() {
CHECK_OBJECT_COERCIBLE(this, "Array.prototype.reverse");
var array = TO_OBJECT_INLINE(this);
var array = TO_OBJECT(this);
var len = TO_UINT32(array.length);
var isArray = IS_ARRAY(array);
@ -662,7 +662,7 @@ function ObservedArrayShift(len) {
function ArrayShift() {
CHECK_OBJECT_COERCIBLE(this, "Array.prototype.shift");
var array = TO_OBJECT_INLINE(this);
var array = TO_OBJECT(this);
var len = TO_UINT32(array.length);
if (len === 0) {
@ -716,7 +716,7 @@ function ArrayUnshift(arg1) { // length == 1
if (%IsObserved(this))
return ObservedArrayUnshift.apply(this, arguments);
var array = TO_OBJECT_INLINE(this);
var array = TO_OBJECT(this);
var len = TO_UINT32(array.length);
var num_arguments = %_ArgumentsLength();
@ -740,7 +740,7 @@ function ArrayUnshift(arg1) { // length == 1
function ArraySlice(start, end) {
CHECK_OBJECT_COERCIBLE(this, "Array.prototype.slice");
var array = TO_OBJECT_INLINE(this);
var array = TO_OBJECT(this);
var len = TO_UINT32(array.length);
var start_i = TO_INTEGER(start);
var end_i = len;
@ -858,7 +858,7 @@ function ArraySplice(start, delete_count) {
return ObservedArraySplice.apply(this, arguments);
var num_arguments = %_ArgumentsLength();
var array = TO_OBJECT_INLINE(this);
var array = TO_OBJECT(this);
var len = TO_UINT32(array.length);
var start_i = ComputeSpliceStartIndex(TO_INTEGER(start), len);
var del_count = ComputeSpliceDeleteCount(delete_count, num_arguments, len,
@ -1190,7 +1190,7 @@ function InnerArraySort(length, comparefn) {
function ArraySort(comparefn) {
CHECK_OBJECT_COERCIBLE(this, "Array.prototype.sort");
var array = $toObject(this);
var array = TO_OBJECT(this);
var length = TO_UINT32(array.length);
return %_CallFunction(array, length, comparefn, InnerArraySort);
}
@ -1217,7 +1217,7 @@ function InnerArrayFilter(f, receiver, array, length) {
var element = array[i];
// Prepare break slots for debugger step in.
if (stepping) %DebugPrepareStepInIfStepping(f);
var new_receiver = needs_wrapper ? $toObject(receiver) : receiver;
var new_receiver = needs_wrapper ? TO_OBJECT(receiver) : receiver;
if (%_CallFunction(new_receiver, element, i, array, f)) {
accumulator[accumulator_length++] = element;
}
@ -1231,7 +1231,7 @@ function ArrayFilter(f, receiver) {
// Pull out the length so that modifications to the length in the
// loop will not affect the looping and side effects are visible.
var array = $toObject(this);
var array = TO_OBJECT(this);
var length = $toUint32(array.length);
var accumulator = InnerArrayFilter(f, receiver, array, length);
var result = new GlobalArray();
@ -1255,7 +1255,7 @@ function InnerArrayForEach(f, receiver, array, length) {
var element = array[i];
// Prepare break slots for debugger step in.
if (stepping) %DebugPrepareStepInIfStepping(f);
var new_receiver = needs_wrapper ? $toObject(receiver) : receiver;
var new_receiver = needs_wrapper ? TO_OBJECT(receiver) : receiver;
%_CallFunction(new_receiver, element, i, array, f);
}
}
@ -1266,7 +1266,7 @@ function ArrayForEach(f, receiver) {
// Pull out the length so that modifications to the length in the
// loop will not affect the looping and side effects are visible.
var array = $toObject(this);
var array = TO_OBJECT(this);
var length = TO_UINT32(array.length);
InnerArrayForEach(f, receiver, array, length);
}
@ -1288,7 +1288,7 @@ function InnerArraySome(f, receiver, array, length) {
var element = array[i];
// Prepare break slots for debugger step in.
if (stepping) %DebugPrepareStepInIfStepping(f);
var new_receiver = needs_wrapper ? $toObject(receiver) : receiver;
var new_receiver = needs_wrapper ? TO_OBJECT(receiver) : receiver;
if (%_CallFunction(new_receiver, element, i, array, f)) return true;
}
}
@ -1303,7 +1303,7 @@ function ArraySome(f, receiver) {
// Pull out the length so that modifications to the length in the
// loop will not affect the looping and side effects are visible.
var array = $toObject(this);
var array = TO_OBJECT(this);
var length = TO_UINT32(array.length);
return InnerArraySome(f, receiver, array, length);
}
@ -1325,7 +1325,7 @@ function InnerArrayEvery(f, receiver, array, length) {
var element = array[i];
// Prepare break slots for debugger step in.
if (stepping) %DebugPrepareStepInIfStepping(f);
var new_receiver = needs_wrapper ? $toObject(receiver) : receiver;
var new_receiver = needs_wrapper ? TO_OBJECT(receiver) : receiver;
if (!%_CallFunction(new_receiver, element, i, array, f)) return false;
}
}
@ -1337,7 +1337,7 @@ function ArrayEvery(f, receiver) {
// Pull out the length so that modifications to the length in the
// loop will not affect the looping and side effects are visible.
var array = $toObject(this);
var array = TO_OBJECT(this);
var length = TO_UINT32(array.length);
return InnerArrayEvery(f, receiver, array, length);
}
@ -1360,7 +1360,7 @@ function InnerArrayMap(f, receiver, array, length) {
var element = array[i];
// Prepare break slots for debugger step in.
if (stepping) %DebugPrepareStepInIfStepping(f);
var new_receiver = needs_wrapper ? $toObject(receiver) : receiver;
var new_receiver = needs_wrapper ? TO_OBJECT(receiver) : receiver;
accumulator[i] = %_CallFunction(new_receiver, element, i, array, f);
}
}
@ -1373,7 +1373,7 @@ function ArrayMap(f, receiver) {
// Pull out the length so that modifications to the length in the
// loop will not affect the looping and side effects are visible.
var array = $toObject(this);
var array = TO_OBJECT(this);
var length = TO_UINT32(array.length);
var accumulator = InnerArrayMap(f, receiver, array, length);
var result = new GlobalArray();
@ -1542,7 +1542,7 @@ function ArrayReduce(callback, current) {
// Pull out the length so that modifications to the length in the
// loop will not affect the looping and side effects are visible.
var array = $toObject(this);
var array = TO_OBJECT(this);
var length = $toUint32(array.length);
return InnerArrayReduce(callback, current, array, length,
%_ArgumentsLength());
@ -1585,7 +1585,7 @@ function ArrayReduceRight(callback, current) {
// Pull out the length so that side effects are visible before the
// callback function is checked.
var array = $toObject(this);
var array = TO_OBJECT(this);
var length = $toUint32(array.length);
return InnerArrayReduceRight(callback, current, array, length,
%_ArgumentsLength());

View File

@ -1724,7 +1724,6 @@ void Genesis::InstallNativeFunctions() {
INSTALL_NATIVE(JSFunction, "$toNumber", to_number_fun);
INSTALL_NATIVE(JSFunction, "$toString", to_string_fun);
INSTALL_NATIVE(JSFunction, "$toDetailString", to_detail_string_fun);
INSTALL_NATIVE(JSFunction, "$toObject", to_object_fun);
INSTALL_NATIVE(JSFunction, "$toInteger", to_integer_fun);
INSTALL_NATIVE(JSFunction, "$toUint32", to_uint32_fun);
INSTALL_NATIVE(JSFunction, "$toInt32", to_int32_fun);

View File

@ -182,7 +182,6 @@ enum BuiltinExtraArguments {
V(CALL_NON_FUNCTION_AS_CONSTRUCTOR, 0) \
V(CALL_FUNCTION_PROXY, 1) \
V(CALL_FUNCTION_PROXY_AS_CONSTRUCTOR, 1) \
V(TO_OBJECT, 0) \
V(TO_NUMBER, 0) \
V(TO_STRING, 0) \
V(TO_NAME, 0) \

View File

@ -177,6 +177,13 @@ Callable CodeFactory::ToNumber(Isolate* isolate) {
}
// static
Callable CodeFactory::ToObject(Isolate* isolate) {
ToObjectStub stub(isolate);
return Callable(stub.GetCode(), stub.GetCallInterfaceDescriptor());
}
// static
Callable CodeFactory::StringAdd(Isolate* isolate, StringAddFlags flags,
PretenureFlag pretenure_flag) {

View File

@ -73,6 +73,7 @@ class CodeFactory final {
ToBooleanStub::Types types = ToBooleanStub::Types());
static Callable ToNumber(Isolate* isolate);
static Callable ToObject(Isolate* isolate);
static Callable StringAdd(Isolate* isolate, StringAddFlags flags,
PretenureFlag pretenure_flag);

View File

@ -1657,6 +1657,16 @@ Handle<Code> ElementsTransitionAndStoreStub::GenerateCode() {
}
template <>
HValue* CodeStubGraphBuilder<ToObjectStub>::BuildCodeStub() {
HValue* receiver = GetParameter(ToObjectDescriptor::kReceiverIndex);
return BuildToObject(receiver);
}
Handle<Code> ToObjectStub::GenerateCode() { return DoGenerateCode(this); }
void CodeStubGraphBuilderBase::BuildCheckAndInstallOptimizedCode(
HValue* js_function,
HValue* native_context,

View File

@ -672,6 +672,11 @@ void ElementsTransitionAndStoreStub::InitializeDescriptor(
}
void ToObjectStub::InitializeDescriptor(CodeStubDescriptor* descriptor) {
descriptor->Initialize(Runtime::FunctionForId(Runtime::kToObject)->entry);
}
CallInterfaceDescriptor StoreTransitionStub::GetCallInterfaceDescriptor()
const {
return StoreTransitionDescriptor(isolate());

View File

@ -54,6 +54,7 @@ namespace internal {
V(StubFailureTrampoline) \
V(SubString) \
V(ToNumber) \
V(ToObject) \
V(VectorStoreICTrampoline) \
V(VectorKeyedStoreICTrampoline) \
V(VectorStoreIC) \
@ -3050,6 +3051,15 @@ class ToNumberStub final : public PlatformCodeStub {
};
class ToObjectStub final : public HydrogenCodeStub {
public:
explicit ToObjectStub(Isolate* isolate) : HydrogenCodeStub(isolate) {}
DEFINE_CALL_INTERFACE_DESCRIPTOR(ToObject);
DEFINE_HYDROGEN_CODE_STUB(ToObject, HydrogenCodeStub);
};
class StringCompareStub : public PlatformCodeStub {
public:
explicit StringCompareStub(Isolate* isolate) : PlatformCodeStub(isolate) {}

View File

@ -268,7 +268,7 @@ function SetForEach(f, receiver) {
while (%SetIteratorNext(iterator, value_array)) {
if (stepping) %DebugPrepareStepInIfStepping(f);
key = value_array[0];
var new_receiver = needs_wrapper ? $toObject(receiver) : receiver;
var new_receiver = needs_wrapper ? TO_OBJECT(receiver) : receiver;
%_CallFunction(new_receiver, key, key, this, f);
}
}
@ -457,7 +457,7 @@ function MapForEach(f, receiver) {
var value_array = [UNDEFINED, UNDEFINED];
while (%MapIteratorNext(iterator, value_array)) {
if (stepping) %DebugPrepareStepInIfStepping(f);
var new_receiver = needs_wrapper ? $toObject(receiver) : receiver;
var new_receiver = needs_wrapper ? TO_OBJECT(receiver) : receiver;
%_CallFunction(new_receiver, value_array[1], value_array[0], this, f);
}
}

View File

@ -307,7 +307,9 @@ void JSGenericLowering::LowerJSToName(Node* node) {
void JSGenericLowering::LowerJSToObject(Node* node) {
ReplaceWithBuiltinCall(node, Builtins::TO_OBJECT, 1);
CallDescriptor::Flags flags = AdjustFrameStatesForCall(node);
Callable callable = CodeFactory::ToObject(isolate());
ReplaceWithStubCall(node, callable, flags);
}

View File

@ -94,6 +94,8 @@ Reduction JSIntrinsicLowering::Reduce(Node* node) {
return ReduceGetTypeFeedbackVector(node);
case Runtime::kInlineGetCallerJSFunction:
return ReduceGetCallerJSFunction(node);
case Runtime::kInlineToObject:
return ReduceToObject(node);
case Runtime::kInlineThrowNotDateError:
return ReduceThrowNotDateError(node);
case Runtime::kInlineCallFunction:
@ -528,6 +530,12 @@ Reduction JSIntrinsicLowering::ReduceThrowNotDateError(Node* node) {
}
Reduction JSIntrinsicLowering::ReduceToObject(Node* node) {
node->set_op(javascript()->ToObject());
return Changed(node);
}
Reduction JSIntrinsicLowering::ReduceCallFunction(Node* node) {
CallRuntimeParameters params = OpParameter<CallRuntimeParameters>(node->op());
size_t arity = params.arity();

View File

@ -58,6 +58,7 @@ class JSIntrinsicLowering final : public AdvancedReducer {
Reduction ReduceGetTypeFeedbackVector(Node* node);
Reduction ReduceGetCallerJSFunction(Node* node);
Reduction ReduceThrowNotDateError(Node* node);
Reduction ReduceToObject(Node* node);
Reduction ReduceCallFunction(Node* node);
Reduction Change(Node* node, const Operator* op);

View File

@ -219,6 +219,7 @@ int Linkage::FrameStateInputCount(Runtime::FunctionId function) {
case Runtime::kInlineGetCallerJSFunction:
case Runtime::kInlineGetPrototype:
case Runtime::kInlineRegExpExec:
case Runtime::kInlineToObject:
return 1;
case Runtime::kInlineDeoptimizeNow:
case Runtime::kInlineThrowNotDateError:

View File

@ -1559,6 +1559,8 @@ Bounds Typer::Visitor::TypeJSCallRuntime(Node* node) {
return Bounds(Type::None(), Type::Range(0, 32, zone()));
case Runtime::kInlineStringGetLength:
return Bounds(Type::None(), Type::Range(0, String::kMaxLength, zone()));
case Runtime::kInlineToObject:
return Bounds(Type::None(), Type::Receiver());
default:
break;
}

View File

@ -97,7 +97,6 @@ enum BindingFlags {
V(TO_NUMBER_FUN_INDEX, JSFunction, to_number_fun) \
V(TO_STRING_FUN_INDEX, JSFunction, to_string_fun) \
V(TO_DETAIL_STRING_FUN_INDEX, JSFunction, to_detail_string_fun) \
V(TO_OBJECT_FUN_INDEX, JSFunction, to_object_fun) \
V(TO_INTEGER_FUN_INDEX, JSFunction, to_integer_fun) \
V(TO_UINT32_FUN_INDEX, JSFunction, to_uint32_fun) \
V(TO_INT32_FUN_INDEX, JSFunction, to_int32_fun) \
@ -363,7 +362,6 @@ class Context: public FixedArray {
TO_NUMBER_FUN_INDEX,
TO_STRING_FUN_INDEX,
TO_DETAIL_STRING_FUN_INDEX,
TO_OBJECT_FUN_INDEX,
TO_INTEGER_FUN_INDEX,
TO_UINT32_FUN_INDEX,
TO_INT32_FUN_INDEX,

View File

@ -775,7 +775,7 @@ function DateToISOString() {
function DateToJSON(key) {
var o = $toObject(this);
var o = TO_OBJECT(this);
var tv = $defaultNumber(o);
if (IS_NUMBER(tv) && !NUMBER_IS_FINITE(tv)) {
return null;

View File

@ -385,7 +385,8 @@ class OptimizedFunctionVisitor BASE_EMBEDDED {
V(kValueMismatch, "value mismatch") \
V(kWrongInstanceType, "wrong instance type") \
V(kWrongMap, "wrong map") \
V(kUndefinedOrNullInForIn, "null or undefined in for-in")
V(kUndefinedOrNullInForIn, "null or undefined in for-in") \
V(kUndefinedOrNullInToObject, "null or undefined in ToObject")
class Deoptimizer : public Malloced {

View File

@ -548,14 +548,6 @@ MaybeHandle<Object> Execution::ToDetailString(
}
MaybeHandle<Object> Execution::ToObject(
Isolate* isolate, Handle<Object> obj) {
if (obj->IsSpecObject()) return obj;
// TODO(verwaest): Use Object::ToObject but throw an exception on failure.
RETURN_NATIVE_CALL(to_object, { obj });
}
MaybeHandle<Object> Execution::ToInteger(
Isolate* isolate, Handle<Object> obj) {
RETURN_NATIVE_CALL(to_integer, { obj });
@ -589,6 +581,16 @@ MaybeHandle<Object> Execution::NewDate(Isolate* isolate, double time) {
#undef RETURN_NATIVE_CALL
MaybeHandle<Object> Execution::ToObject(Isolate* isolate, Handle<Object> obj) {
Handle<JSReceiver> receiver;
if (JSReceiver::ToObject(isolate, obj).ToHandle(&receiver)) {
return receiver;
}
THROW_NEW_ERROR(
isolate, NewTypeError(MessageTemplate::kUndefinedOrNullToObject), Object);
}
MaybeHandle<JSRegExp> Execution::NewJSRegExp(Handle<String> pattern,
Handle<String> flags) {
Isolate* isolate = pattern->GetIsolate();

View File

@ -1083,8 +1083,8 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
__ CompareObjectType(r0, r1, r1, FIRST_SPEC_OBJECT_TYPE);
__ b(ge, &done_convert);
__ bind(&convert);
__ push(r0);
__ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
ToObjectStub stub(isolate());
__ CallStub(&stub);
__ bind(&done_convert);
PrepareForBailoutForId(stmt->ToObjectId(), TOS_REG);
__ push(r0);
@ -4018,6 +4018,19 @@ void FullCodeGenerator::EmitNumberToString(CallRuntime* expr) {
}
void FullCodeGenerator::EmitToObject(CallRuntime* expr) {
ZoneList<Expression*>* args = expr->arguments();
DCHECK_EQ(1, args->length());
// Load the argument into r0 and convert it.
VisitForAccumulatorValue(args->at(0));
ToObjectStub stub(isolate());
__ CallStub(&stub);
context()->Plug(r0);
}
void FullCodeGenerator::EmitStringCharFromCode(CallRuntime* expr) {
ZoneList<Expression*>* args = expr->arguments();
DCHECK(args->length() == 1);

View File

@ -1085,8 +1085,8 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
__ JumpIfSmi(x0, &convert);
__ JumpIfObjectType(x0, x10, x11, FIRST_SPEC_OBJECT_TYPE, &done_convert, ge);
__ Bind(&convert);
__ Push(x0);
__ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
ToObjectStub stub(isolate());
__ CallStub(&stub);
__ Bind(&done_convert);
PrepareForBailoutForId(stmt->ToObjectId(), TOS_REG);
__ Push(x0);
@ -3726,6 +3726,19 @@ void FullCodeGenerator::EmitNumberToString(CallRuntime* expr) {
}
void FullCodeGenerator::EmitToObject(CallRuntime* expr) {
ZoneList<Expression*>* args = expr->arguments();
DCHECK_EQ(1, args->length());
// Load the argument into x0 and convert it.
VisitForAccumulatorValue(args->at(0));
ToObjectStub stub(isolate());
__ CallStub(&stub);
context()->Plug(x0);
}
void FullCodeGenerator::EmitStringCharFromCode(CallRuntime* expr) {
ZoneList<Expression*>* args = expr->arguments();
DCHECK(args->length() == 1);

View File

@ -531,6 +531,7 @@ class FullCodeGenerator: public AstVisitor {
F(RegExpConstructResult) \
F(GetFromCache) \
F(NumberToString) \
F(ToObject) \
F(DebugIsActive)
#define GENERATOR_DECLARATION(Name) void Emit##Name(CallRuntime* call);

View File

@ -1025,8 +1025,8 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
__ CmpObjectType(eax, FIRST_SPEC_OBJECT_TYPE, ecx);
__ j(above_equal, &done_convert, Label::kNear);
__ bind(&convert);
__ push(eax);
__ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
ToObjectStub stub(isolate());
__ CallStub(&stub);
__ bind(&done_convert);
PrepareForBailoutForId(stmt->ToObjectId(), TOS_REG);
__ push(eax);
@ -3921,6 +3921,19 @@ void FullCodeGenerator::EmitNumberToString(CallRuntime* expr) {
}
void FullCodeGenerator::EmitToObject(CallRuntime* expr) {
ZoneList<Expression*>* args = expr->arguments();
DCHECK_EQ(1, args->length());
// Load the argument into eax and convert it.
VisitForAccumulatorValue(args->at(0));
ToObjectStub stub(isolate());
__ CallStub(&stub);
context()->Plug(eax);
}
void FullCodeGenerator::EmitStringCharFromCode(CallRuntime* expr) {
ZoneList<Expression*>* args = expr->arguments();
DCHECK(args->length() == 1);

View File

@ -1085,8 +1085,8 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
__ GetObjectType(a0, a1, a1);
__ Branch(&done_convert, ge, a1, Operand(FIRST_SPEC_OBJECT_TYPE));
__ bind(&convert);
__ push(a0);
__ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
ToObjectStub stub(isolate());
__ CallStub(&stub);
__ mov(a0, v0);
__ bind(&done_convert);
PrepareForBailoutForId(stmt->ToObjectId(), TOS_REG);
@ -4028,6 +4028,20 @@ void FullCodeGenerator::EmitNumberToString(CallRuntime* expr) {
}
void FullCodeGenerator::EmitToObject(CallRuntime* expr) {
ZoneList<Expression*>* args = expr->arguments();
DCHECK_EQ(1, args->length());
// Load the argument into a0 and convert it.
VisitForAccumulatorValue(args->at(0));
__ mov(a0, result_register());
ToObjectStub stub(isolate());
__ CallStub(&stub);
context()->Plug(v0);
}
void FullCodeGenerator::EmitStringCharFromCode(CallRuntime* expr) {
ZoneList<Expression*>* args = expr->arguments();
DCHECK(args->length() == 1);

View File

@ -1082,8 +1082,8 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
__ GetObjectType(a0, a1, a1);
__ Branch(&done_convert, ge, a1, Operand(FIRST_SPEC_OBJECT_TYPE));
__ bind(&convert);
__ push(a0);
__ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
ToObjectStub stub(isolate());
__ CallStub(&stub);
__ mov(a0, v0);
__ bind(&done_convert);
PrepareForBailoutForId(stmt->ToObjectId(), TOS_REG);
@ -4031,6 +4031,20 @@ void FullCodeGenerator::EmitNumberToString(CallRuntime* expr) {
}
void FullCodeGenerator::EmitToObject(CallRuntime* expr) {
ZoneList<Expression*>* args = expr->arguments();
DCHECK_EQ(1, args->length());
// Load the argument into a0 and convert it.
VisitForAccumulatorValue(args->at(0));
__ mov(a0, result_register());
ToObjectStub stub(isolate());
__ CallStub(&stub);
context()->Plug(v0);
}
void FullCodeGenerator::EmitStringCharFromCode(CallRuntime* expr) {
ZoneList<Expression*>* args = expr->arguments();
DCHECK(args->length() == 1);

View File

@ -1046,8 +1046,8 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
__ CompareObjectType(r3, r4, r4, FIRST_SPEC_OBJECT_TYPE);
__ bge(&done_convert);
__ bind(&convert);
__ push(r3);
__ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
ToObjectStub stub(isolate());
__ CallStub(&stub);
__ bind(&done_convert);
PrepareForBailoutForId(stmt->ToObjectId(), TOS_REG);
__ push(r3);
@ -4029,6 +4029,18 @@ void FullCodeGenerator::EmitNumberToString(CallRuntime* expr) {
}
void FullCodeGenerator::EmitToObject(CallRuntime* expr) {
ZoneList<Expression*>* args = expr->arguments();
DCHECK_EQ(1, args->length());
// Load the argument into r3 and convert it.
VisitForAccumulatorValue(args->at(0));
ToObjectStub stub(isolate());
__ CallStub(&stub);
context()->Plug(r3);
}
void FullCodeGenerator::EmitStringCharFromCode(CallRuntime* expr) {
ZoneList<Expression*>* args = expr->arguments();
DCHECK(args->length() == 1);

View File

@ -1039,12 +1039,12 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
// Convert the object to a JS object.
Label convert, done_convert;
__ JumpIfSmi(rax, &convert);
__ JumpIfSmi(rax, &convert, Label::kNear);
__ CmpObjectType(rax, FIRST_SPEC_OBJECT_TYPE, rcx);
__ j(above_equal, &done_convert);
__ j(above_equal, &done_convert, Label::kNear);
__ bind(&convert);
__ Push(rax);
__ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
ToObjectStub stub(isolate());
__ CallStub(&stub);
__ bind(&done_convert);
PrepareForBailoutForId(stmt->ToObjectId(), TOS_REG);
__ Push(rax);
@ -3912,6 +3912,19 @@ void FullCodeGenerator::EmitNumberToString(CallRuntime* expr) {
}
void FullCodeGenerator::EmitToObject(CallRuntime* expr) {
ZoneList<Expression*>* args = expr->arguments();
DCHECK_EQ(1, args->length());
// Load the argument into rax and convert it.
VisitForAccumulatorValue(args->at(0));
ToObjectStub stub(isolate());
__ CallStub(&stub);
context()->Plug(rax);
}
void FullCodeGenerator::EmitStringCharFromCode(CallRuntime* expr) {
ZoneList<Expression*>* args = expr->arguments();
DCHECK(args->length() == 1);

View File

@ -1018,8 +1018,8 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
__ CmpObjectType(eax, FIRST_SPEC_OBJECT_TYPE, ecx);
__ j(above_equal, &done_convert, Label::kNear);
__ bind(&convert);
__ push(eax);
__ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
ToObjectStub stub(isolate());
__ CallStub(&stub);
__ bind(&done_convert);
PrepareForBailoutForId(stmt->ToObjectId(), TOS_REG);
__ push(eax);
@ -3912,6 +3912,19 @@ void FullCodeGenerator::EmitNumberToString(CallRuntime* expr) {
}
void FullCodeGenerator::EmitToObject(CallRuntime* expr) {
ZoneList<Expression*>* args = expr->arguments();
DCHECK_EQ(1, args->length());
// Load the argument into eax and convert it.
VisitForAccumulatorValue(args->at(0));
ToObjectStub stub(isolate());
__ CallStub(&stub);
context()->Plug(eax);
}
void FullCodeGenerator::EmitStringCharFromCode(CallRuntime* expr) {
ZoneList<Expression*>* args = expr->arguments();
DCHECK(args->length() == 1);

View File

@ -16,7 +16,7 @@ var GlobalArray = global.Array;
// https://github.com/tc39/Array.prototype.includes
// 6e3b78c927aeda20b9d40e81303f9d44596cd904
function ArrayIncludes(searchElement, fromIndex) {
var array = $toObject(this);
var array = TO_OBJECT(this);
var len = $toLength(array.length);
if (len === 0) {

View File

@ -83,7 +83,7 @@ function InnerArrayCopyWithin(target, start, end, array, length) {
function ArrayCopyWithin(target, start, end) {
CHECK_OBJECT_COERCIBLE(this, "Array.prototype.copyWithin");
var array = TO_OBJECT_INLINE(this);
var array = TO_OBJECT(this);
var length = $toLength(array.length);
return InnerArrayCopyWithin(target, start, end, array, length);
@ -103,7 +103,7 @@ function InnerArrayFind(predicate, thisArg, array, length) {
for (var i = 0; i < length; i++) {
var element = array[i];
var newThisArg = needs_wrapper ? $toObject(thisArg) : thisArg;
var newThisArg = needs_wrapper ? TO_OBJECT(thisArg) : thisArg;
if (%_CallFunction(newThisArg, element, i, array, predicate)) {
return element;
}
@ -116,7 +116,7 @@ function InnerArrayFind(predicate, thisArg, array, length) {
function ArrayFind(predicate, thisArg) {
CHECK_OBJECT_COERCIBLE(this, "Array.prototype.find");
var array = $toObject(this);
var array = TO_OBJECT(this);
var length = $toInteger(array.length);
return InnerArrayFind(predicate, thisArg, array, length);
@ -136,7 +136,7 @@ function InnerArrayFindIndex(predicate, thisArg, array, length) {
for (var i = 0; i < length; i++) {
var element = array[i];
var newThisArg = needs_wrapper ? $toObject(thisArg) : thisArg;
var newThisArg = needs_wrapper ? TO_OBJECT(thisArg) : thisArg;
if (%_CallFunction(newThisArg, element, i, array, predicate)) {
return i;
}
@ -149,7 +149,7 @@ function InnerArrayFindIndex(predicate, thisArg, array, length) {
function ArrayFindIndex(predicate, thisArg) {
CHECK_OBJECT_COERCIBLE(this, "Array.prototype.findIndex");
var array = $toObject(this);
var array = TO_OBJECT(this);
var length = $toInteger(array.length);
return InnerArrayFindIndex(predicate, thisArg, array, length);
@ -187,7 +187,7 @@ function InnerArrayFill(value, start, end, array, length) {
function ArrayFill(value, start, end) {
CHECK_OBJECT_COERCIBLE(this, "Array.prototype.fill");
var array = $toObject(this);
var array = TO_OBJECT(this);
var length = TO_UINT32(array.length);
return InnerArrayFill(value, start, end, array, length);
@ -205,7 +205,7 @@ function AddArrayElement(constructor, array, i, value) {
// ES6, draft 10-14-14, section 22.1.2.1
function ArrayFrom(arrayLike, mapfn, receiver) {
var items = $toObject(arrayLike);
var items = TO_OBJECT(arrayLike);
var mapping = !IS_UNDEFINED(mapfn);
if (mapping) {
@ -215,7 +215,7 @@ function ArrayFrom(arrayLike, mapfn, receiver) {
if (IS_NULL(receiver)) {
receiver = UNDEFINED;
} else if (!IS_UNDEFINED(receiver)) {
receiver = TO_OBJECT_INLINE(receiver);
receiver = TO_OBJECT(receiver);
}
}
}

View File

@ -24,7 +24,7 @@ utils.Import(function(from) {
// ES6, draft 04-03-15, section 19.1.2.1
function ObjectAssign(target, sources) {
var to = TO_OBJECT_INLINE(target);
var to = TO_OBJECT(target);
var argsLen = %_ArgumentsLength();
if (argsLen < 2) return to;
@ -34,7 +34,7 @@ function ObjectAssign(target, sources) {
continue;
}
var from = TO_OBJECT_INLINE(nextSource);
var from = TO_OBJECT(nextSource);
var keys = OwnPropertyKeys(from);
var len = keys.length;

View File

@ -2032,6 +2032,165 @@ HValue* HGraphBuilder::BuildNumberToString(HValue* object, Type* type) {
}
HValue* HGraphBuilder::BuildToObject(HValue* receiver) {
NoObservableSideEffectsScope scope(this);
// Create a joinable continuation.
HIfContinuation wrap(graph()->CreateBasicBlock(),
graph()->CreateBasicBlock());
// Determine the proper global constructor function required to wrap
// {receiver} into a JSValue, unless {receiver} is already a {JSReceiver}, in
// which case we just return it. Deopts to Runtime::kToObject if {receiver}
// is undefined or null.
IfBuilder receiver_is_smi(this);
receiver_is_smi.If<HIsSmiAndBranch>(receiver);
receiver_is_smi.Then();
{
// Load native context.
HValue* native_context = BuildGetNativeContext();
// Load global Number function.
HValue* constructor = Add<HLoadNamedField>(
native_context, nullptr,
HObjectAccess::ForContextSlot(Context::NUMBER_FUNCTION_INDEX));
Push(constructor);
}
receiver_is_smi.Else();
{
// Determine {receiver} map and instance type.
HValue* receiver_map =
Add<HLoadNamedField>(receiver, nullptr, HObjectAccess::ForMap());
HValue* receiver_instance_type = Add<HLoadNamedField>(
receiver_map, nullptr, HObjectAccess::ForMapInstanceType());
// First check whether {receiver} is already a spec object (fast case).
IfBuilder receiver_is_not_spec_object(this);
receiver_is_not_spec_object.If<HCompareNumericAndBranch>(
receiver_instance_type, Add<HConstant>(FIRST_SPEC_OBJECT_TYPE),
Token::LT);
receiver_is_not_spec_object.Then();
{
// Load native context.
HValue* native_context = BuildGetNativeContext();
IfBuilder receiver_is_heap_number(this);
receiver_is_heap_number.If<HCompareNumericAndBranch>(
receiver_instance_type, Add<HConstant>(HEAP_NUMBER_TYPE), Token::EQ);
receiver_is_heap_number.Then();
{
// Load global Number function.
HValue* constructor = Add<HLoadNamedField>(
native_context, nullptr,
HObjectAccess::ForContextSlot(Context::NUMBER_FUNCTION_INDEX));
Push(constructor);
}
receiver_is_heap_number.Else();
{
// Load boolean map (we cannot decide based on instance type, because
// it's ODDBALL_TYPE, which would also include null and undefined).
HValue* boolean_map = Add<HLoadRoot>(Heap::kBooleanMapRootIndex);
IfBuilder receiver_is_boolean(this);
receiver_is_boolean.If<HCompareObjectEqAndBranch>(receiver_map,
boolean_map);
receiver_is_boolean.Then();
{
// Load global Boolean function.
HValue* constructor = Add<HLoadNamedField>(
native_context, nullptr,
HObjectAccess::ForContextSlot(Context::BOOLEAN_FUNCTION_INDEX));
Push(constructor);
}
receiver_is_boolean.Else();
{
IfBuilder receiver_is_string(this);
receiver_is_string.If<HCompareNumericAndBranch>(
receiver_instance_type, Add<HConstant>(FIRST_NONSTRING_TYPE),
Token::LT);
receiver_is_string.Then();
{
// Load global String function.
HValue* constructor = Add<HLoadNamedField>(
native_context, nullptr,
HObjectAccess::ForContextSlot(Context::STRING_FUNCTION_INDEX));
Push(constructor);
}
receiver_is_string.Else();
{
IfBuilder receiver_is_symbol(this);
receiver_is_symbol.If<HCompareNumericAndBranch>(
receiver_instance_type, Add<HConstant>(SYMBOL_TYPE), Token::EQ);
receiver_is_symbol.Then();
{
// Load global Symbol function.
HValue* constructor = Add<HLoadNamedField>(
native_context, nullptr, HObjectAccess::ForContextSlot(
Context::SYMBOL_FUNCTION_INDEX));
Push(constructor);
}
receiver_is_symbol.Else();
{
IfBuilder receiver_is_float32x4(this);
receiver_is_float32x4.If<HCompareNumericAndBranch>(
receiver_instance_type, Add<HConstant>(FLOAT32X4_TYPE),
Token::EQ);
receiver_is_float32x4.Then();
{
// Load global Float32x4 function.
HValue* constructor = Add<HLoadNamedField>(
native_context, nullptr,
HObjectAccess::ForContextSlot(
Context::FLOAT32X4_FUNCTION_INDEX));
Push(constructor);
}
receiver_is_float32x4.ElseDeopt(
Deoptimizer::kUndefinedOrNullInToObject);
receiver_is_float32x4.JoinContinuation(&wrap);
}
receiver_is_symbol.JoinContinuation(&wrap);
}
receiver_is_string.JoinContinuation(&wrap);
}
receiver_is_boolean.JoinContinuation(&wrap);
}
receiver_is_heap_number.JoinContinuation(&wrap);
}
receiver_is_not_spec_object.JoinContinuation(&wrap);
}
receiver_is_smi.JoinContinuation(&wrap);
// Wrap the receiver if necessary.
IfBuilder if_wrap(this, &wrap);
if_wrap.Then();
{
// Determine the initial map for the global constructor.
HValue* constructor = Pop();
HValue* constructor_initial_map = Add<HLoadNamedField>(
constructor, nullptr, HObjectAccess::ForPrototypeOrInitialMap());
// Allocate and initialize a JSValue wrapper.
HValue* value =
BuildAllocate(Add<HConstant>(JSValue::kSize), HType::JSObject(),
JS_VALUE_TYPE, HAllocationMode());
Add<HStoreNamedField>(value, HObjectAccess::ForMap(),
constructor_initial_map);
HValue* empty_fixed_array = Add<HLoadRoot>(Heap::kEmptyFixedArrayRootIndex);
Add<HStoreNamedField>(value, HObjectAccess::ForPropertiesPointer(),
empty_fixed_array);
Add<HStoreNamedField>(value, HObjectAccess::ForElementsPointer(),
empty_fixed_array);
Add<HStoreNamedField>(value, HObjectAccess::ForObservableJSObjectOffset(
JSValue::kValueOffset),
receiver);
Push(value);
}
if_wrap.Else();
{ Push(receiver); }
if_wrap.End();
return Pop();
}
HAllocate* HGraphBuilder::BuildAllocate(
HValue* object_size,
HType type,

View File

@ -1329,6 +1329,7 @@ class HGraphBuilder {
bool is_jsarray);
HValue* BuildNumberToString(HValue* object, Type* type);
HValue* BuildToObject(HValue* receiver);
void BuildJSObjectCheck(HValue* receiver,
int bit_field_mask);

View File

@ -251,7 +251,7 @@ function supportedLocalesOf(service, locales, options) {
if (IS_UNDEFINED(options)) {
options = {};
} else {
options = $toObject(options);
options = TO_OBJECT(options);
}
var matcher = options.localeMatcher;
@ -717,7 +717,7 @@ function initializeLocaleList(locales) {
return freezeArray(seen);
}
var o = $toObject(locales);
var o = TO_OBJECT(locales);
var len = TO_UINT32(o.length);
for (var k = 0; k < len; k++) {
@ -951,7 +951,7 @@ function initializeCollator(collator, locales, options) {
return new Intl.Collator(locales, options);
}
return initializeCollator($toObject(this), locales, options);
return initializeCollator(TO_OBJECT(this), locales, options);
},
DONT_ENUM
);
@ -1192,7 +1192,7 @@ function initializeNumberFormat(numberFormat, locales, options) {
return new Intl.NumberFormat(locales, options);
}
return initializeNumberFormat($toObject(this), locales, options);
return initializeNumberFormat(TO_OBJECT(this), locales, options);
},
DONT_ENUM
);
@ -1444,7 +1444,7 @@ function toDateTimeOptions(options, required, defaults) {
if (IS_UNDEFINED(options)) {
options = {};
} else {
options = TO_OBJECT_INLINE(options);
options = TO_OBJECT(options);
}
var needsDefault = true;
@ -1594,7 +1594,7 @@ function initializeDateTimeFormat(dateFormat, locales, options) {
return new Intl.DateTimeFormat(locales, options);
}
return initializeDateTimeFormat($toObject(this), locales, options);
return initializeDateTimeFormat(TO_OBJECT(this), locales, options);
},
DONT_ENUM
);
@ -1814,7 +1814,7 @@ function initializeBreakIterator(iterator, locales, options) {
return new Intl.v8BreakIterator(locales, options);
}
return initializeBreakIterator($toObject(this), locales, options);
return initializeBreakIterator(TO_OBJECT(this), locales, options);
},
DONT_ENUM
);

View File

@ -994,8 +994,9 @@ void Builtins::Generate_FunctionCall(MacroAssembler* masm) {
__ SmiTag(eax);
__ push(eax);
__ push(ebx);
__ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
__ mov(eax, ebx);
ToObjectStub stub(masm->isolate());
__ CallStub(&stub);
__ mov(ebx, eax);
__ Move(edx, Immediate(0)); // restore
@ -1215,8 +1216,9 @@ static void Generate_ApplyHelper(MacroAssembler* masm, bool targetIsArgument) {
__ j(above_equal, &push_receiver);
__ bind(&call_to_object);
__ push(ebx);
__ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
__ mov(eax, ebx);
ToObjectStub stub(masm->isolate());
__ CallStub(&stub);
__ mov(ebx, eax);
__ jmp(&push_receiver);

View File

@ -2093,8 +2093,8 @@ static void EmitWrapCase(MacroAssembler* masm, int argc, Label* cont) {
// Wrap the receiver and patch it back onto the stack.
{ FrameScope frame_scope(masm, StackFrame::INTERNAL);
__ push(edi);
__ push(eax);
__ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
ToObjectStub stub(masm->isolate());
__ CallStub(&stub);
__ pop(edi);
}
__ mov(Operand(esp, (argc + 1) * kPointerSize), eax);

View File

@ -103,6 +103,10 @@ void ToNumberDescriptor::InitializePlatformSpecific(
}
// static
const Register ToObjectDescriptor::ReceiverRegister() { return eax; }
void NumberToStringDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
Register registers[] = {eax};

View File

@ -155,6 +155,13 @@ void InstanceofDescriptor::InitializePlatformSpecific(
}
void ToObjectDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
Register registers[] = {ReceiverRegister()};
data->InitializePlatformSpecific(arraysize(registers), registers);
}
void MathPowTaggedDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
Register registers[] = {exponent()};

View File

@ -24,6 +24,7 @@ class PlatformInterfaceDescriptor;
V(FastNewClosure) \
V(FastNewContext) \
V(ToNumber) \
V(ToObject) \
V(NumberToString) \
V(Typeof) \
V(FastCloneShallowArray) \
@ -339,6 +340,16 @@ class ToNumberDescriptor : public CallInterfaceDescriptor {
};
class ToObjectDescriptor : public CallInterfaceDescriptor {
public:
enum ParameterIndices { kReceiverIndex };
DECLARE_DESCRIPTOR(ToObjectDescriptor, CallInterfaceDescriptor)
static const Register ReceiverRegister();
};
class NumberToStringDescriptor : public CallInterfaceDescriptor {
public:
DECLARE_DESCRIPTOR(NumberToStringDescriptor, CallInterfaceDescriptor)

View File

@ -154,7 +154,7 @@ macro TO_INT32(arg) = (%_IsSmi(%IS_VAR(arg)) ? arg : (arg >> 0));
macro TO_UINT32(arg) = (arg >>> 0);
macro TO_STRING_INLINE(arg) = (IS_STRING(%IS_VAR(arg)) ? arg : $nonStringToString(arg));
macro TO_NUMBER_INLINE(arg) = (IS_NUMBER(%IS_VAR(arg)) ? arg : $nonNumberToNumber(arg));
macro TO_OBJECT_INLINE(arg) = (IS_SPEC_OBJECT(%IS_VAR(arg)) ? arg : $toObject(arg));
macro TO_OBJECT(arg) = (%_ToObject(arg));
macro JSON_NUMBER_TO_STRING(arg) = ((%_IsSmi(%IS_VAR(arg)) || arg - arg == 0) ? %_NumberToString(arg) : "null");
macro HAS_OWN_PROPERTY(arg, index) = (%_CallFunction(arg, index, ObjectHasOwnProperty));
macro SHOULD_CREATE_WRAPPER(functionName, receiver) = (!IS_SPEC_OBJECT(receiver) && %IsSloppyModeFunction(functionName));

View File

@ -67,7 +67,7 @@ var GlobalEvalError;
function NoSideEffectsObjectToString() {
if (IS_UNDEFINED(this) && !IS_UNDETECTABLE(this)) return "[object Undefined]";
if (IS_NULL(this)) return "[object Null]";
return "[object " + %_ClassOf(TO_OBJECT_INLINE(this)) + "]";
return "[object " + %_ClassOf(TO_OBJECT(this)) + "]";
}

View File

@ -1313,8 +1313,10 @@ void Builtins::Generate_FunctionCall(MacroAssembler* masm) {
{
FrameScope scope(masm, StackFrame::INTERNAL);
__ sll(a0, a0, kSmiTagSize); // Smi tagged.
__ Push(a0, a2);
__ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
__ push(a0);
__ mov(a0, a2);
ToObjectStub stub(masm->isolate());
__ CallStub(&stub);
__ mov(a2, v0);
__ pop(a0);
@ -1548,8 +1550,8 @@ static void Generate_ApplyHelper(MacroAssembler* masm, bool targetIsArgument) {
// Convert the receiver to a regular object.
// a0: receiver
__ bind(&call_to_object);
__ push(a0);
__ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
ToObjectStub stub(masm->isolate());
__ CallStub(&stub);
__ mov(a0, v0); // Put object in a0 to match other paths to push_receiver.
__ Branch(&push_receiver);

View File

@ -2675,8 +2675,10 @@ static void EmitSlowCase(MacroAssembler* masm,
static void EmitWrapCase(MacroAssembler* masm, int argc, Label* cont) {
// Wrap the receiver and patch it back onto the stack.
{ FrameScope frame_scope(masm, StackFrame::INTERNAL);
__ Push(a1, a3);
__ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
__ Push(a1);
__ mov(a0, a3);
ToObjectStub stub(masm->isolate());
__ CallStub(&stub);
__ pop(a1);
}
__ Branch(USE_DELAY_SLOT, cont);

View File

@ -95,6 +95,10 @@ void ToNumberDescriptor::InitializePlatformSpecific(
}
// static
const Register ToObjectDescriptor::ReceiverRegister() { return a0; }
void NumberToStringDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
Register registers[] = {a0};

View File

@ -1309,8 +1309,10 @@ void Builtins::Generate_FunctionCall(MacroAssembler* masm) {
{
FrameScope scope(masm, StackFrame::INTERNAL);
__ SmiTag(a0);
__ Push(a0, a2);
__ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
__ Push(a0);
__ mov(a0, a2);
ToObjectStub stub(masm->isolate());
__ CallStub(&stub);
__ mov(a2, v0);
__ pop(a0);
@ -1545,8 +1547,8 @@ static void Generate_ApplyHelper(MacroAssembler* masm, bool targetIsArgument) {
// Convert the receiver to a regular object.
// a0: receiver
__ bind(&call_to_object);
__ push(a0);
__ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
ToObjectStub stub(masm->isolate());
__ CallStub(&stub);
__ mov(a0, v0); // Put object in a0 to match other paths to push_receiver.
__ Branch(&push_receiver);

View File

@ -2714,8 +2714,10 @@ static void EmitSlowCase(MacroAssembler* masm,
static void EmitWrapCase(MacroAssembler* masm, int argc, Label* cont) {
// Wrap the receiver and patch it back onto the stack.
{ FrameScope frame_scope(masm, StackFrame::INTERNAL);
__ Push(a1, a3);
__ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
__ Push(a1);
__ mov(a0, a3);
ToObjectStub stub(masm->isolate());
__ CallStub(&stub);
__ pop(a1);
}
__ Branch(USE_DELAY_SLOT, cont);

View File

@ -95,6 +95,10 @@ void ToNumberDescriptor::InitializePlatformSpecific(
}
// static
const Register ToObjectDescriptor::ReceiverRegister() { return a0; }
void NumberToStringDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
Register registers[] = {a0};

View File

@ -1338,8 +1338,10 @@ void Builtins::Generate_FunctionCall(MacroAssembler* masm) {
// Enter an internal frame in order to preserve argument count.
FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL);
__ SmiTag(r3);
__ Push(r3, r5);
__ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
__ Push(r3);
__ mr(r3, r5);
ToObjectStub stub(masm->isolate());
__ CallStub(&stub);
__ mr(r5, r3);
__ pop(r3);
@ -1592,8 +1594,8 @@ static void Generate_ApplyHelper(MacroAssembler* masm, bool targetIsArgument) {
// Convert the receiver to a regular object.
// r3: receiver
__ bind(&call_to_object);
__ push(r3);
__ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
ToObjectStub stub(masm->isolate());
__ CallStub(&stub);
__ b(&push_receiver);
__ bind(&use_global_proxy);

View File

@ -2726,8 +2726,10 @@ static void EmitWrapCase(MacroAssembler* masm, int argc, Label* cont) {
// Wrap the receiver and patch it back onto the stack.
{
FrameAndConstantPoolScope frame_scope(masm, StackFrame::INTERNAL);
__ Push(r4, r6);
__ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
__ push(r4);
__ mr(r3, r6);
ToObjectStub stub(masm->isolate());
__ CallStub(&stub);
__ pop(r4);
}
__ StoreP(r3, MemOperand(sp, argc * kPointerSize), r0);

View File

@ -95,6 +95,10 @@ void ToNumberDescriptor::InitializePlatformSpecific(
}
// static
const Register ToObjectDescriptor::ReceiverRegister() { return r3; }
void NumberToStringDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
Register registers[] = {r3};

View File

@ -58,7 +58,6 @@ var APPLY_PREPARE;
var REFLECT_APPLY_PREPARE;
var REFLECT_CONSTRUCT_PREPARE;
var STACK_OVERFLOW;
var TO_OBJECT;
var TO_NUMBER;
var TO_STRING;
var TO_NAME;
@ -76,7 +75,6 @@ var $toInteger;
var $toLength;
var $toName;
var $toNumber;
var $toObject;
var $toPositiveInteger;
var $toPrimitive;
var $toString;
@ -512,7 +510,7 @@ SHR_STRONG = function SHR_STRONG(y) {
// ECMA-262, section 11.4.1, page 46.
DELETE = function DELETE(key, language_mode) {
return %DeleteProperty(%$toObject(this), key, language_mode);
return %DeleteProperty(TO_OBJECT(this), key, language_mode);
}
@ -730,12 +728,6 @@ STACK_OVERFLOW = function STACK_OVERFLOW(length) {
}
// Convert the receiver to an object - forward to ToObject.
TO_OBJECT = function TO_OBJECT() {
return %$toObject(this);
}
// Convert the receiver to a number - forward to ToNumber.
TO_NUMBER = function TO_NUMBER() {
return %$toNumber(this);
@ -832,20 +824,6 @@ function ToName(x) {
}
// ECMA-262, section 9.9, page 36.
function ToObject(x) {
if (IS_STRING(x)) return new GlobalString(x);
if (IS_NUMBER(x)) return new GlobalNumber(x);
if (IS_BOOLEAN(x)) return new GlobalBoolean(x);
if (IS_SYMBOL(x)) return %NewSymbolWrapper(x);
if (IS_FLOAT32X4(x)) return %NewFloat32x4Wrapper(x);
if (IS_NULL_OR_UNDEFINED(x) && !IS_UNDETECTABLE(x)) {
throw MakeTypeError(kUndefinedOrNullToObject);
}
return x;
}
// ECMA-262, section 9.4, page 34.
function ToInteger(x) {
if (%_IsSmi(x)) return x;
@ -1006,7 +984,6 @@ $toInteger = ToInteger;
$toLength = ToLength;
$toName = ToName;
$toNumber = ToNumber;
$toObject = ToObject;
$toPositiveInteger = ToPositiveInteger;
$toPrimitive = ToPrimitive;
$toString = ToString;

View File

@ -1461,5 +1461,19 @@ RUNTIME_FUNCTION(Runtime_DefineSetterPropertyUnchecked) {
setter, attrs));
return isolate->heap()->undefined_value();
}
RUNTIME_FUNCTION(Runtime_ToObject) {
HandleScope scope(isolate);
DCHECK_EQ(1, args.length());
CONVERT_ARG_HANDLE_CHECKED(Object, object, 0);
Handle<JSReceiver> receiver;
if (JSReceiver::ToObject(isolate, object).ToHandle(&receiver)) {
return *receiver;
}
THROW_NEW_ERROR_RETURN_FAILURE(
isolate, NewTypeError(MessageTemplate::kUndefinedOrNullToObject));
}
} // namespace internal
} // namespace v8

View File

@ -33,14 +33,6 @@
NumberTo##type##Component(*y), NumberTo##type##Component(*z)); \
}
#define SIMD_CREATE_WRAPPER_FUNCTION(type) \
RUNTIME_FUNCTION(Runtime_New##type##Wrapper) { \
HandleScope scope(isolate); \
DCHECK(args.length() == 1); \
CONVERT_ARG_HANDLE_CHECKED(type, value, 0); \
return *Object::ToObject(isolate, value).ToHandleChecked(); \
}
#define SIMD_CHECK_FUNCTION(type) \
RUNTIME_FUNCTION(Runtime_##type##Check) { \
HandleScope scope(isolate); \
@ -101,7 +93,6 @@
#define SIMD4_FUNCTIONS(type) \
SIMD4_CREATE_FUNCTION(type) \
SIMD_CREATE_WRAPPER_FUNCTION(type) \
SIMD_CHECK_FUNCTION(type) \
SIMD4_EXTRACT_LANE_FUNCTION(type) \
SIMD4_EQUALS_FUNCTION(type) \
@ -125,5 +116,6 @@ inline bool Equals(float x, float y) { return x == y; }
} // namespace
SIMD4_FUNCTIONS(Float32x4)
}
} // namespace v8::internal
} // namespace internal
} // namespace v8

View File

@ -51,14 +51,6 @@ RUNTIME_FUNCTION(Runtime_CreateGlobalPrivateSymbol) {
}
RUNTIME_FUNCTION(Runtime_NewSymbolWrapper) {
HandleScope scope(isolate);
DCHECK(args.length() == 1);
CONVERT_ARG_HANDLE_CHECKED(Symbol, symbol, 0);
return *Object::ToObject(isolate, symbol).ToHandleChecked();
}
RUNTIME_FUNCTION(Runtime_SymbolDescription) {
SealHandleScope shs(isolate);
DCHECK(args.length() == 1);

View File

@ -497,7 +497,8 @@ namespace internal {
F(IsStrong, 1, 1) \
F(ClassOf, 1, 1) \
F(DefineGetterPropertyUnchecked, 4, 1) \
F(DefineSetterPropertyUnchecked, 4, 1)
F(DefineSetterPropertyUnchecked, 4, 1) \
F(ToObject, 1, 1)
#define FOR_EACH_INTRINSIC_OBSERVE(F) \
@ -570,7 +571,6 @@ namespace internal {
#define FOR_EACH_INTRINSIC_SIMD(F) \
F(CreateFloat32x4, 4, 1) \
F(NewFloat32x4Wrapper, 1, 1) \
F(Float32x4Check, 1, 1) \
F(Float32x4ExtractLane, 2, 1) \
F(Float32x4Equals, 2, 1) \
@ -620,7 +620,6 @@ namespace internal {
F(CreateSymbol, 1, 1) \
F(CreatePrivateSymbol, 1, 1) \
F(CreateGlobalPrivateSymbol, 1, 1) \
F(NewSymbolWrapper, 1, 1) \
F(SymbolDescription, 1, 1) \
F(SymbolRegistry, 0, 1) \
F(SymbolIsPrivate, 1, 1)

View File

@ -41,7 +41,7 @@ function CreateStringIterator(string) {
// 21.1.5.2.1 %StringIteratorPrototype%.next( )
function StringIteratorNext() {
var iterator = $toObject(this);
var iterator = TO_OBJECT(this);
if (!HAS_DEFINED_PRIVATE(iterator, stringIteratorNextIndexSymbol)) {
throw MakeTypeError(kIncompatibleMethodReceiver,

View File

@ -1112,8 +1112,8 @@ function StringFromCodePoint(_) { // length = 1
function StringRaw(callSite) {
// TODO(caitp): Use rest parameters when implemented
var numberOfSubstitutions = %_ArgumentsLength();
var cooked = $toObject(callSite);
var raw = $toObject(cooked.raw);
var cooked = TO_OBJECT(callSite);
var raw = TO_OBJECT(cooked.raw);
var literalSegments = $toLength(raw.length);
if (literalSegments <= 0) return "";

View File

@ -78,7 +78,7 @@ function SymbolKeyFor(symbol) {
// ES6 19.1.2.8
function ObjectGetOwnPropertySymbols(obj) {
obj = $toObject(obj);
obj = TO_OBJECT(obj);
// TODO(arv): Proxies use a shared trap for String and Symbol keys.

View File

@ -141,7 +141,7 @@ utils.InstallFunctions(global, DONT_ENUM, [
function ObjectToString() {
if (IS_UNDEFINED(this) && !IS_UNDETECTABLE(this)) return "[object Undefined]";
if (IS_NULL(this)) return "[object Null]";
var O = TO_OBJECT_INLINE(this);
var O = TO_OBJECT(this);
var builtinTag = %_ClassOf(O);
var tag;
@ -168,14 +168,14 @@ function ObjectToLocaleString() {
// ECMA-262 - 15.2.4.4
function ObjectValueOf() {
return TO_OBJECT_INLINE(this);
return TO_OBJECT(this);
}
// ECMA-262 - 15.2.4.5
function ObjectHasOwnProperty(value) {
var name = $toName(value);
var object = TO_OBJECT_INLINE(this);
var object = TO_OBJECT(this);
if (%_IsJSProxy(object)) {
// TODO(rossberg): adjust once there is a story for symbols vs proxies.
@ -206,7 +206,7 @@ function ObjectPropertyIsEnumerable(V) {
var desc = GetOwnPropertyJS(this, P);
return IS_UNDEFINED(desc) ? false : desc.isEnumerable();
}
return %IsPropertyEnumerable(TO_OBJECT_INLINE(this), P);
return %IsPropertyEnumerable(TO_OBJECT(this), P);
}
@ -223,7 +223,7 @@ function ObjectDefineGetter(name, fun) {
desc.setGet(fun);
desc.setEnumerable(true);
desc.setConfigurable(true);
DefineOwnProperty(TO_OBJECT_INLINE(receiver), $toName(name), desc, false);
DefineOwnProperty(TO_OBJECT(receiver), $toName(name), desc, false);
}
@ -232,7 +232,7 @@ function ObjectLookupGetter(name) {
if (receiver == null && !IS_UNDETECTABLE(receiver)) {
receiver = %GlobalProxy(ObjectLookupGetter);
}
return %LookupAccessor(TO_OBJECT_INLINE(receiver), $toName(name), GETTER);
return %LookupAccessor(TO_OBJECT(receiver), $toName(name), GETTER);
}
@ -248,7 +248,7 @@ function ObjectDefineSetter(name, fun) {
desc.setSet(fun);
desc.setEnumerable(true);
desc.setConfigurable(true);
DefineOwnProperty(TO_OBJECT_INLINE(receiver), $toName(name), desc, false);
DefineOwnProperty(TO_OBJECT(receiver), $toName(name), desc, false);
}
@ -257,12 +257,12 @@ function ObjectLookupSetter(name) {
if (receiver == null && !IS_UNDETECTABLE(receiver)) {
receiver = %GlobalProxy(ObjectLookupSetter);
}
return %LookupAccessor(TO_OBJECT_INLINE(receiver), $toName(name), SETTER);
return %LookupAccessor(TO_OBJECT(receiver), $toName(name), SETTER);
}
function ObjectKeys(obj) {
obj = TO_OBJECT_INLINE(obj);
obj = TO_OBJECT(obj);
if (%_IsJSProxy(obj)) {
var handler = %GetHandler(obj);
var names = CallTrap0(handler, "keys", ProxyDerivedKeysTrap);
@ -579,7 +579,7 @@ function GetOwnPropertyJS(obj, v) {
// GetOwnProperty returns an array indexed by the constants
// defined in macros.py.
// If p is not a property on obj undefined is returned.
var props = %GetOwnProperty(TO_OBJECT_INLINE(obj), p);
var props = %GetOwnProperty(TO_OBJECT(obj), p);
return ConvertDescriptorArrayToDescriptor(props);
}
@ -868,7 +868,7 @@ function DefineOwnPropertyFromAPI(obj, p, value, desc) {
// ES6 section 19.1.2.9
function ObjectGetPrototypeOf(obj) {
return %_GetPrototype(TO_OBJECT_INLINE(obj));
return %_GetPrototype(TO_OBJECT(obj));
}
// ES6 section 19.1.2.19.
@ -889,7 +889,7 @@ function ObjectSetPrototypeOf(obj, proto) {
// ES6 section 19.1.2.6
function ObjectGetOwnPropertyDescriptor(obj, p) {
var desc = GetOwnPropertyJS(TO_OBJECT_INLINE(obj), p);
var desc = GetOwnPropertyJS(TO_OBJECT(obj), p);
return FromPropertyDescriptor(desc);
}
@ -1001,7 +1001,7 @@ function OwnPropertyKeys(obj) {
// ES5 section 15.2.3.4.
function ObjectGetOwnPropertyNames(obj) {
obj = TO_OBJECT_INLINE(obj);
obj = TO_OBJECT(obj);
// Special handling for proxies.
if (%_IsJSProxy(obj)) {
var handler = %GetHandler(obj);
@ -1093,7 +1093,7 @@ function ObjectDefineProperties(obj, properties) {
if (!IS_SPEC_OBJECT(obj)) {
throw MakeTypeError(kCalledOnNonObject, "Object.defineProperties");
}
var props = TO_OBJECT_INLINE(properties);
var props = TO_OBJECT(properties);
var names = GetOwnEnumerablePropertyNames(props);
var descriptors = new InternalArray();
for (var i = 0; i < names.length; i++) {
@ -1263,7 +1263,7 @@ function ObjectIs(obj1, obj2) {
// ECMA-262, Edition 6, section B.2.2.1.1
function ObjectGetProto() {
return %_GetPrototype(TO_OBJECT_INLINE(this));
return %_GetPrototype(TO_OBJECT(this));
}
@ -1280,10 +1280,10 @@ function ObjectSetProto(proto) {
function ObjectConstructor(x) {
if (%_IsConstructCall()) {
if (x == null) return this;
return TO_OBJECT_INLINE(x);
return TO_OBJECT(x);
} else {
if (x == null) return { };
return TO_OBJECT_INLINE(x);
return TO_OBJECT(x);
}
}

View File

@ -1053,8 +1053,9 @@ void Builtins::Generate_FunctionCall(MacroAssembler* masm) {
__ Integer32ToSmi(rax, rax);
__ Push(rax);
__ Push(rbx);
__ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
__ movp(rax, rbx);
ToObjectStub stub(masm->isolate());
__ CallStub(&stub);
__ movp(rbx, rax);
__ Set(rdx, 0); // indicate regular JS_FUNCTION
@ -1274,8 +1275,9 @@ static void Generate_ApplyHelper(MacroAssembler* masm, bool targetIsArgument) {
// Convert the receiver to an object.
__ bind(&call_to_object);
__ Push(rbx);
__ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
__ movp(rax, rbx);
ToObjectStub stub(masm->isolate());
__ CallStub(&stub);
__ movp(rbx, rax);
__ jmp(&push_receiver, Label::kNear);

View File

@ -1964,8 +1964,8 @@ static void EmitWrapCase(MacroAssembler* masm,
// Wrap the receiver and patch it back onto the stack.
{ FrameScope frame_scope(masm, StackFrame::INTERNAL);
__ Push(rdi);
__ Push(rax);
__ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
ToObjectStub stub(masm->isolate());
__ CallStub(&stub);
__ Pop(rdi);
}
__ movp(args->GetReceiverOperand(), rax);

View File

@ -103,6 +103,10 @@ void ToNumberDescriptor::InitializePlatformSpecific(
}
// static
const Register ToObjectDescriptor::ReceiverRegister() { return rax; }
void NumberToStringDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
Register registers[] = {rax};

View File

@ -994,8 +994,9 @@ void Builtins::Generate_FunctionCall(MacroAssembler* masm) {
__ SmiTag(eax);
__ push(eax);
__ push(ebx);
__ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
__ mov(eax, ebx);
ToObjectStub stub(masm->isolate());
__ CallStub(&stub);
__ mov(ebx, eax);
__ Move(edx, Immediate(0)); // restore
@ -1215,8 +1216,9 @@ static void Generate_ApplyHelper(MacroAssembler* masm, bool targetIsArgument) {
__ j(above_equal, &push_receiver);
__ bind(&call_to_object);
__ push(ebx);
__ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
__ mov(eax, ebx);
ToObjectStub stub(masm->isolate());
__ CallStub(&stub);
__ mov(ebx, eax);
__ jmp(&push_receiver);

View File

@ -1800,8 +1800,8 @@ static void EmitWrapCase(MacroAssembler* masm, int argc, Label* cont) {
// Wrap the receiver and patch it back onto the stack.
{ FrameScope frame_scope(masm, StackFrame::INTERNAL);
__ push(edi);
__ push(eax);
__ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
ToObjectStub stub(masm->isolate());
__ CallStub(&stub);
__ pop(edi);
}
__ mov(Operand(esp, (argc + 1) * kPointerSize), eax);

View File

@ -103,6 +103,10 @@ void ToNumberDescriptor::InitializePlatformSpecific(
}
// static
const Register ToObjectDescriptor::ReceiverRegister() { return eax; }
void NumberToStringDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
Register registers[] = {eax};