[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:
parent
f8a4afa7bd
commit
4fc6f54724
@ -6913,7 +6913,7 @@ class Internals {
|
|||||||
static const int kJSObjectHeaderSize = 3 * kApiPointerSize;
|
static const int kJSObjectHeaderSize = 3 * kApiPointerSize;
|
||||||
static const int kFixedArrayHeaderSize = 2 * kApiPointerSize;
|
static const int kFixedArrayHeaderSize = 2 * kApiPointerSize;
|
||||||
static const int kContextHeaderSize = 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 kFullStringRepresentationMask = 0x07;
|
||||||
static const int kStringEncodingMask = 0x4;
|
static const int kStringEncodingMask = 0x4;
|
||||||
static const int kExternalTwoByteRepresentationTag = 0x02;
|
static const int kExternalTwoByteRepresentationTag = 0x02;
|
||||||
|
@ -1319,8 +1319,9 @@ void Builtins::Generate_FunctionCall(MacroAssembler* masm) {
|
|||||||
__ SmiTag(r0);
|
__ SmiTag(r0);
|
||||||
__ push(r0);
|
__ push(r0);
|
||||||
|
|
||||||
__ push(r2);
|
__ mov(r0, r2);
|
||||||
__ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
|
ToObjectStub stub(masm->isolate());
|
||||||
|
__ CallStub(&stub);
|
||||||
__ mov(r2, r0);
|
__ mov(r2, r0);
|
||||||
|
|
||||||
__ pop(r0);
|
__ pop(r0);
|
||||||
@ -1556,8 +1557,8 @@ static void Generate_ApplyHelper(MacroAssembler* masm, bool targetIsArgument) {
|
|||||||
// Convert the receiver to a regular object.
|
// Convert the receiver to a regular object.
|
||||||
// r0: receiver
|
// r0: receiver
|
||||||
__ bind(&call_to_object);
|
__ bind(&call_to_object);
|
||||||
__ push(r0);
|
ToObjectStub stub(masm->isolate());
|
||||||
__ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
|
__ CallStub(&stub);
|
||||||
__ b(&push_receiver);
|
__ b(&push_receiver);
|
||||||
|
|
||||||
__ bind(&use_global_proxy);
|
__ bind(&use_global_proxy);
|
||||||
|
@ -2547,8 +2547,10 @@ static void EmitSlowCase(MacroAssembler* masm,
|
|||||||
static void EmitWrapCase(MacroAssembler* masm, int argc, Label* cont) {
|
static void EmitWrapCase(MacroAssembler* masm, int argc, Label* cont) {
|
||||||
// Wrap the receiver and patch it back onto the stack.
|
// Wrap the receiver and patch it back onto the stack.
|
||||||
{ FrameAndConstantPoolScope frame_scope(masm, StackFrame::INTERNAL);
|
{ FrameAndConstantPoolScope frame_scope(masm, StackFrame::INTERNAL);
|
||||||
__ Push(r1, r3);
|
__ push(r1);
|
||||||
__ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
|
__ mov(r0, r3);
|
||||||
|
ToObjectStub stub(masm->isolate());
|
||||||
|
__ CallStub(&stub);
|
||||||
__ pop(r1);
|
__ pop(r1);
|
||||||
}
|
}
|
||||||
__ str(r0, MemOperand(sp, argc * kPointerSize));
|
__ str(r0, MemOperand(sp, argc * kPointerSize));
|
||||||
|
@ -95,6 +95,10 @@ void ToNumberDescriptor::InitializePlatformSpecific(
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// static
|
||||||
|
const Register ToObjectDescriptor::ReceiverRegister() { return r0; }
|
||||||
|
|
||||||
|
|
||||||
void NumberToStringDescriptor::InitializePlatformSpecific(
|
void NumberToStringDescriptor::InitializePlatformSpecific(
|
||||||
CallInterfaceDescriptorData* data) {
|
CallInterfaceDescriptorData* data) {
|
||||||
Register registers[] = {r0};
|
Register registers[] = {r0};
|
||||||
|
@ -1355,8 +1355,10 @@ void Builtins::Generate_FunctionCall(MacroAssembler* masm) {
|
|||||||
FrameScope scope(masm, StackFrame::INTERNAL);
|
FrameScope scope(masm, StackFrame::INTERNAL);
|
||||||
__ SmiTag(argc);
|
__ SmiTag(argc);
|
||||||
|
|
||||||
__ Push(argc, receiver);
|
__ Push(argc);
|
||||||
__ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
|
__ Mov(x0, receiver);
|
||||||
|
ToObjectStub stub(masm->isolate());
|
||||||
|
__ CallStub(&stub);
|
||||||
__ Mov(receiver, x0);
|
__ Mov(receiver, x0);
|
||||||
|
|
||||||
__ Pop(argc);
|
__ 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.
|
// Call a builtin to convert the receiver to a regular object.
|
||||||
__ Bind(&convert_receiver_to_object);
|
__ Bind(&convert_receiver_to_object);
|
||||||
__ Push(receiver);
|
__ Mov(x0, receiver);
|
||||||
__ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
|
ToObjectStub stub(masm->isolate());
|
||||||
|
__ CallStub(&stub);
|
||||||
__ Mov(receiver, x0);
|
__ Mov(receiver, x0);
|
||||||
__ B(&push_receiver);
|
__ B(&push_receiver);
|
||||||
|
|
||||||
|
@ -2921,8 +2921,10 @@ static void EmitSlowCase(MacroAssembler* masm,
|
|||||||
static void EmitWrapCase(MacroAssembler* masm, int argc, Label* cont) {
|
static void EmitWrapCase(MacroAssembler* masm, int argc, Label* cont) {
|
||||||
// Wrap the receiver and patch it back onto the stack.
|
// Wrap the receiver and patch it back onto the stack.
|
||||||
{ FrameScope frame_scope(masm, StackFrame::INTERNAL);
|
{ FrameScope frame_scope(masm, StackFrame::INTERNAL);
|
||||||
__ Push(x1, x3);
|
__ Push(x1);
|
||||||
__ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
|
__ Mov(x0, x3);
|
||||||
|
ToObjectStub stub(masm->isolate());
|
||||||
|
__ CallStub(&stub);
|
||||||
__ Pop(x1);
|
__ Pop(x1);
|
||||||
}
|
}
|
||||||
__ Poke(x0, argc * kPointerSize);
|
__ Poke(x0, argc * kPointerSize);
|
||||||
|
@ -104,6 +104,10 @@ void ToNumberDescriptor::InitializePlatformSpecific(
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// static
|
||||||
|
const Register ToObjectDescriptor::ReceiverRegister() { return x0; }
|
||||||
|
|
||||||
|
|
||||||
void NumberToStringDescriptor::InitializePlatformSpecific(
|
void NumberToStringDescriptor::InitializePlatformSpecific(
|
||||||
CallInterfaceDescriptorData* data) {
|
CallInterfaceDescriptorData* data) {
|
||||||
// x0: value
|
// x0: value
|
||||||
|
@ -45,7 +45,7 @@ function ArrayIterator() {}
|
|||||||
|
|
||||||
// 15.4.5.1 CreateArrayIterator Abstract Operation
|
// 15.4.5.1 CreateArrayIterator Abstract Operation
|
||||||
function CreateArrayIterator(array, kind) {
|
function CreateArrayIterator(array, kind) {
|
||||||
var object = $toObject(array);
|
var object = TO_OBJECT(array);
|
||||||
var iterator = new ArrayIterator;
|
var iterator = new ArrayIterator;
|
||||||
SET_PRIVATE(iterator, arrayIteratorObjectSymbol, object);
|
SET_PRIVATE(iterator, arrayIteratorObjectSymbol, object);
|
||||||
SET_PRIVATE(iterator, arrayIteratorNextIndexSymbol, 0);
|
SET_PRIVATE(iterator, arrayIteratorNextIndexSymbol, 0);
|
||||||
@ -68,7 +68,7 @@ function ArrayIteratorIterator() {
|
|||||||
|
|
||||||
// 15.4.5.2.2 ArrayIterator.prototype.next( )
|
// 15.4.5.2.2 ArrayIterator.prototype.next( )
|
||||||
function ArrayIteratorNext() {
|
function ArrayIteratorNext() {
|
||||||
var iterator = $toObject(this);
|
var iterator = TO_OBJECT(this);
|
||||||
|
|
||||||
if (!HAS_DEFINED_PRIVATE(iterator, arrayIteratorNextIndexSymbol)) {
|
if (!HAS_DEFINED_PRIVATE(iterator, arrayIteratorNextIndexSymbol)) {
|
||||||
throw MakeTypeError(kIncompatibleMethodReceiver,
|
throw MakeTypeError(kIncompatibleMethodReceiver,
|
||||||
|
50
src/array.js
50
src/array.js
@ -227,7 +227,7 @@ function ConvertToLocaleString(e) {
|
|||||||
// According to ES5, section 15.4.4.3, the toLocaleString conversion
|
// According to ES5, section 15.4.4.3, the toLocaleString conversion
|
||||||
// must throw a TypeError if ToObject(e).toLocaleString isn't
|
// must throw a TypeError if ToObject(e).toLocaleString isn't
|
||||||
// callable.
|
// callable.
|
||||||
var e_obj = $toObject(e);
|
var e_obj = TO_OBJECT(e);
|
||||||
return $toString(e_obj.toLocaleString());
|
return $toString(e_obj.toLocaleString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -388,7 +388,7 @@ function ArrayToString() {
|
|||||||
}
|
}
|
||||||
array = this;
|
array = this;
|
||||||
} else {
|
} else {
|
||||||
array = $toObject(this);
|
array = TO_OBJECT(this);
|
||||||
func = array.join;
|
func = array.join;
|
||||||
}
|
}
|
||||||
if (!IS_SPEC_FUNCTION(func)) {
|
if (!IS_SPEC_FUNCTION(func)) {
|
||||||
@ -406,7 +406,7 @@ function InnerArrayToLocaleString(array, length) {
|
|||||||
|
|
||||||
|
|
||||||
function ArrayToLocaleString() {
|
function ArrayToLocaleString() {
|
||||||
var array = $toObject(this);
|
var array = TO_OBJECT(this);
|
||||||
var arrayLen = array.length;
|
var arrayLen = array.length;
|
||||||
return InnerArrayToLocaleString(array, arrayLen);
|
return InnerArrayToLocaleString(array, arrayLen);
|
||||||
}
|
}
|
||||||
@ -437,7 +437,7 @@ function InnerArrayJoin(separator, array, length) {
|
|||||||
function ArrayJoin(separator) {
|
function ArrayJoin(separator) {
|
||||||
CHECK_OBJECT_COERCIBLE(this, "Array.prototype.join");
|
CHECK_OBJECT_COERCIBLE(this, "Array.prototype.join");
|
||||||
|
|
||||||
var array = TO_OBJECT_INLINE(this);
|
var array = TO_OBJECT(this);
|
||||||
var length = TO_UINT32(array.length);
|
var length = TO_UINT32(array.length);
|
||||||
|
|
||||||
return InnerArrayJoin(separator, array, length);
|
return InnerArrayJoin(separator, array, length);
|
||||||
@ -466,7 +466,7 @@ function ObservedArrayPop(n) {
|
|||||||
function ArrayPop() {
|
function ArrayPop() {
|
||||||
CHECK_OBJECT_COERCIBLE(this, "Array.prototype.pop");
|
CHECK_OBJECT_COERCIBLE(this, "Array.prototype.pop");
|
||||||
|
|
||||||
var array = TO_OBJECT_INLINE(this);
|
var array = TO_OBJECT(this);
|
||||||
var n = TO_UINT32(array.length);
|
var n = TO_UINT32(array.length);
|
||||||
if (n == 0) {
|
if (n == 0) {
|
||||||
array.length = n;
|
array.length = n;
|
||||||
@ -512,7 +512,7 @@ function ArrayPush() {
|
|||||||
if (%IsObserved(this))
|
if (%IsObserved(this))
|
||||||
return ObservedArrayPush.apply(this, arguments);
|
return ObservedArrayPush.apply(this, arguments);
|
||||||
|
|
||||||
var array = TO_OBJECT_INLINE(this);
|
var array = TO_OBJECT(this);
|
||||||
var n = TO_UINT32(array.length);
|
var n = TO_UINT32(array.length);
|
||||||
var m = %_ArgumentsLength();
|
var m = %_ArgumentsLength();
|
||||||
|
|
||||||
@ -532,7 +532,7 @@ function ArrayPush() {
|
|||||||
function ArrayConcatJS(arg1) { // length == 1
|
function ArrayConcatJS(arg1) { // length == 1
|
||||||
CHECK_OBJECT_COERCIBLE(this, "Array.prototype.concat");
|
CHECK_OBJECT_COERCIBLE(this, "Array.prototype.concat");
|
||||||
|
|
||||||
var array = $toObject(this);
|
var array = TO_OBJECT(this);
|
||||||
var arg_count = %_ArgumentsLength();
|
var arg_count = %_ArgumentsLength();
|
||||||
var arrays = new InternalArray(1 + arg_count);
|
var arrays = new InternalArray(1 + arg_count);
|
||||||
arrays[0] = array;
|
arrays[0] = array;
|
||||||
@ -627,7 +627,7 @@ function GenericArrayReverse(array, len) {
|
|||||||
function ArrayReverse() {
|
function ArrayReverse() {
|
||||||
CHECK_OBJECT_COERCIBLE(this, "Array.prototype.reverse");
|
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 len = TO_UINT32(array.length);
|
||||||
var isArray = IS_ARRAY(array);
|
var isArray = IS_ARRAY(array);
|
||||||
|
|
||||||
@ -662,7 +662,7 @@ function ObservedArrayShift(len) {
|
|||||||
function ArrayShift() {
|
function ArrayShift() {
|
||||||
CHECK_OBJECT_COERCIBLE(this, "Array.prototype.shift");
|
CHECK_OBJECT_COERCIBLE(this, "Array.prototype.shift");
|
||||||
|
|
||||||
var array = TO_OBJECT_INLINE(this);
|
var array = TO_OBJECT(this);
|
||||||
var len = TO_UINT32(array.length);
|
var len = TO_UINT32(array.length);
|
||||||
|
|
||||||
if (len === 0) {
|
if (len === 0) {
|
||||||
@ -716,7 +716,7 @@ function ArrayUnshift(arg1) { // length == 1
|
|||||||
if (%IsObserved(this))
|
if (%IsObserved(this))
|
||||||
return ObservedArrayUnshift.apply(this, arguments);
|
return ObservedArrayUnshift.apply(this, arguments);
|
||||||
|
|
||||||
var array = TO_OBJECT_INLINE(this);
|
var array = TO_OBJECT(this);
|
||||||
var len = TO_UINT32(array.length);
|
var len = TO_UINT32(array.length);
|
||||||
var num_arguments = %_ArgumentsLength();
|
var num_arguments = %_ArgumentsLength();
|
||||||
|
|
||||||
@ -740,7 +740,7 @@ function ArrayUnshift(arg1) { // length == 1
|
|||||||
function ArraySlice(start, end) {
|
function ArraySlice(start, end) {
|
||||||
CHECK_OBJECT_COERCIBLE(this, "Array.prototype.slice");
|
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 len = TO_UINT32(array.length);
|
||||||
var start_i = TO_INTEGER(start);
|
var start_i = TO_INTEGER(start);
|
||||||
var end_i = len;
|
var end_i = len;
|
||||||
@ -858,7 +858,7 @@ function ArraySplice(start, delete_count) {
|
|||||||
return ObservedArraySplice.apply(this, arguments);
|
return ObservedArraySplice.apply(this, arguments);
|
||||||
|
|
||||||
var num_arguments = %_ArgumentsLength();
|
var num_arguments = %_ArgumentsLength();
|
||||||
var array = TO_OBJECT_INLINE(this);
|
var array = TO_OBJECT(this);
|
||||||
var len = TO_UINT32(array.length);
|
var len = TO_UINT32(array.length);
|
||||||
var start_i = ComputeSpliceStartIndex(TO_INTEGER(start), len);
|
var start_i = ComputeSpliceStartIndex(TO_INTEGER(start), len);
|
||||||
var del_count = ComputeSpliceDeleteCount(delete_count, num_arguments, len,
|
var del_count = ComputeSpliceDeleteCount(delete_count, num_arguments, len,
|
||||||
@ -1190,7 +1190,7 @@ function InnerArraySort(length, comparefn) {
|
|||||||
function ArraySort(comparefn) {
|
function ArraySort(comparefn) {
|
||||||
CHECK_OBJECT_COERCIBLE(this, "Array.prototype.sort");
|
CHECK_OBJECT_COERCIBLE(this, "Array.prototype.sort");
|
||||||
|
|
||||||
var array = $toObject(this);
|
var array = TO_OBJECT(this);
|
||||||
var length = TO_UINT32(array.length);
|
var length = TO_UINT32(array.length);
|
||||||
return %_CallFunction(array, length, comparefn, InnerArraySort);
|
return %_CallFunction(array, length, comparefn, InnerArraySort);
|
||||||
}
|
}
|
||||||
@ -1217,7 +1217,7 @@ function InnerArrayFilter(f, receiver, array, length) {
|
|||||||
var element = array[i];
|
var element = array[i];
|
||||||
// Prepare break slots for debugger step in.
|
// Prepare break slots for debugger step in.
|
||||||
if (stepping) %DebugPrepareStepInIfStepping(f);
|
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)) {
|
if (%_CallFunction(new_receiver, element, i, array, f)) {
|
||||||
accumulator[accumulator_length++] = element;
|
accumulator[accumulator_length++] = element;
|
||||||
}
|
}
|
||||||
@ -1231,7 +1231,7 @@ function ArrayFilter(f, receiver) {
|
|||||||
|
|
||||||
// Pull out the length so that modifications to the length in the
|
// Pull out the length so that modifications to the length in the
|
||||||
// loop will not affect the looping and side effects are visible.
|
// 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 length = $toUint32(array.length);
|
||||||
var accumulator = InnerArrayFilter(f, receiver, array, length);
|
var accumulator = InnerArrayFilter(f, receiver, array, length);
|
||||||
var result = new GlobalArray();
|
var result = new GlobalArray();
|
||||||
@ -1255,7 +1255,7 @@ function InnerArrayForEach(f, receiver, array, length) {
|
|||||||
var element = array[i];
|
var element = array[i];
|
||||||
// Prepare break slots for debugger step in.
|
// Prepare break slots for debugger step in.
|
||||||
if (stepping) %DebugPrepareStepInIfStepping(f);
|
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);
|
%_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
|
// Pull out the length so that modifications to the length in the
|
||||||
// loop will not affect the looping and side effects are visible.
|
// 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 length = TO_UINT32(array.length);
|
||||||
InnerArrayForEach(f, receiver, array, length);
|
InnerArrayForEach(f, receiver, array, length);
|
||||||
}
|
}
|
||||||
@ -1288,7 +1288,7 @@ function InnerArraySome(f, receiver, array, length) {
|
|||||||
var element = array[i];
|
var element = array[i];
|
||||||
// Prepare break slots for debugger step in.
|
// Prepare break slots for debugger step in.
|
||||||
if (stepping) %DebugPrepareStepInIfStepping(f);
|
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;
|
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
|
// Pull out the length so that modifications to the length in the
|
||||||
// loop will not affect the looping and side effects are visible.
|
// 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 length = TO_UINT32(array.length);
|
||||||
return InnerArraySome(f, receiver, array, length);
|
return InnerArraySome(f, receiver, array, length);
|
||||||
}
|
}
|
||||||
@ -1325,7 +1325,7 @@ function InnerArrayEvery(f, receiver, array, length) {
|
|||||||
var element = array[i];
|
var element = array[i];
|
||||||
// Prepare break slots for debugger step in.
|
// Prepare break slots for debugger step in.
|
||||||
if (stepping) %DebugPrepareStepInIfStepping(f);
|
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;
|
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
|
// Pull out the length so that modifications to the length in the
|
||||||
// loop will not affect the looping and side effects are visible.
|
// 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 length = TO_UINT32(array.length);
|
||||||
return InnerArrayEvery(f, receiver, array, length);
|
return InnerArrayEvery(f, receiver, array, length);
|
||||||
}
|
}
|
||||||
@ -1360,7 +1360,7 @@ function InnerArrayMap(f, receiver, array, length) {
|
|||||||
var element = array[i];
|
var element = array[i];
|
||||||
// Prepare break slots for debugger step in.
|
// Prepare break slots for debugger step in.
|
||||||
if (stepping) %DebugPrepareStepInIfStepping(f);
|
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);
|
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
|
// Pull out the length so that modifications to the length in the
|
||||||
// loop will not affect the looping and side effects are visible.
|
// 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 length = TO_UINT32(array.length);
|
||||||
var accumulator = InnerArrayMap(f, receiver, array, length);
|
var accumulator = InnerArrayMap(f, receiver, array, length);
|
||||||
var result = new GlobalArray();
|
var result = new GlobalArray();
|
||||||
@ -1542,7 +1542,7 @@ function ArrayReduce(callback, current) {
|
|||||||
|
|
||||||
// Pull out the length so that modifications to the length in the
|
// Pull out the length so that modifications to the length in the
|
||||||
// loop will not affect the looping and side effects are visible.
|
// 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 length = $toUint32(array.length);
|
||||||
return InnerArrayReduce(callback, current, array, length,
|
return InnerArrayReduce(callback, current, array, length,
|
||||||
%_ArgumentsLength());
|
%_ArgumentsLength());
|
||||||
@ -1585,7 +1585,7 @@ function ArrayReduceRight(callback, current) {
|
|||||||
|
|
||||||
// Pull out the length so that side effects are visible before the
|
// Pull out the length so that side effects are visible before the
|
||||||
// callback function is checked.
|
// callback function is checked.
|
||||||
var array = $toObject(this);
|
var array = TO_OBJECT(this);
|
||||||
var length = $toUint32(array.length);
|
var length = $toUint32(array.length);
|
||||||
return InnerArrayReduceRight(callback, current, array, length,
|
return InnerArrayReduceRight(callback, current, array, length,
|
||||||
%_ArgumentsLength());
|
%_ArgumentsLength());
|
||||||
|
@ -1724,7 +1724,6 @@ void Genesis::InstallNativeFunctions() {
|
|||||||
INSTALL_NATIVE(JSFunction, "$toNumber", to_number_fun);
|
INSTALL_NATIVE(JSFunction, "$toNumber", to_number_fun);
|
||||||
INSTALL_NATIVE(JSFunction, "$toString", to_string_fun);
|
INSTALL_NATIVE(JSFunction, "$toString", to_string_fun);
|
||||||
INSTALL_NATIVE(JSFunction, "$toDetailString", to_detail_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, "$toInteger", to_integer_fun);
|
||||||
INSTALL_NATIVE(JSFunction, "$toUint32", to_uint32_fun);
|
INSTALL_NATIVE(JSFunction, "$toUint32", to_uint32_fun);
|
||||||
INSTALL_NATIVE(JSFunction, "$toInt32", to_int32_fun);
|
INSTALL_NATIVE(JSFunction, "$toInt32", to_int32_fun);
|
||||||
|
@ -182,7 +182,6 @@ enum BuiltinExtraArguments {
|
|||||||
V(CALL_NON_FUNCTION_AS_CONSTRUCTOR, 0) \
|
V(CALL_NON_FUNCTION_AS_CONSTRUCTOR, 0) \
|
||||||
V(CALL_FUNCTION_PROXY, 1) \
|
V(CALL_FUNCTION_PROXY, 1) \
|
||||||
V(CALL_FUNCTION_PROXY_AS_CONSTRUCTOR, 1) \
|
V(CALL_FUNCTION_PROXY_AS_CONSTRUCTOR, 1) \
|
||||||
V(TO_OBJECT, 0) \
|
|
||||||
V(TO_NUMBER, 0) \
|
V(TO_NUMBER, 0) \
|
||||||
V(TO_STRING, 0) \
|
V(TO_STRING, 0) \
|
||||||
V(TO_NAME, 0) \
|
V(TO_NAME, 0) \
|
||||||
|
@ -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
|
// static
|
||||||
Callable CodeFactory::StringAdd(Isolate* isolate, StringAddFlags flags,
|
Callable CodeFactory::StringAdd(Isolate* isolate, StringAddFlags flags,
|
||||||
PretenureFlag pretenure_flag) {
|
PretenureFlag pretenure_flag) {
|
||||||
|
@ -73,6 +73,7 @@ class CodeFactory final {
|
|||||||
ToBooleanStub::Types types = ToBooleanStub::Types());
|
ToBooleanStub::Types types = ToBooleanStub::Types());
|
||||||
|
|
||||||
static Callable ToNumber(Isolate* isolate);
|
static Callable ToNumber(Isolate* isolate);
|
||||||
|
static Callable ToObject(Isolate* isolate);
|
||||||
|
|
||||||
static Callable StringAdd(Isolate* isolate, StringAddFlags flags,
|
static Callable StringAdd(Isolate* isolate, StringAddFlags flags,
|
||||||
PretenureFlag pretenure_flag);
|
PretenureFlag pretenure_flag);
|
||||||
|
@ -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(
|
void CodeStubGraphBuilderBase::BuildCheckAndInstallOptimizedCode(
|
||||||
HValue* js_function,
|
HValue* js_function,
|
||||||
HValue* native_context,
|
HValue* native_context,
|
||||||
|
@ -672,6 +672,11 @@ void ElementsTransitionAndStoreStub::InitializeDescriptor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void ToObjectStub::InitializeDescriptor(CodeStubDescriptor* descriptor) {
|
||||||
|
descriptor->Initialize(Runtime::FunctionForId(Runtime::kToObject)->entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
CallInterfaceDescriptor StoreTransitionStub::GetCallInterfaceDescriptor()
|
CallInterfaceDescriptor StoreTransitionStub::GetCallInterfaceDescriptor()
|
||||||
const {
|
const {
|
||||||
return StoreTransitionDescriptor(isolate());
|
return StoreTransitionDescriptor(isolate());
|
||||||
|
@ -54,6 +54,7 @@ namespace internal {
|
|||||||
V(StubFailureTrampoline) \
|
V(StubFailureTrampoline) \
|
||||||
V(SubString) \
|
V(SubString) \
|
||||||
V(ToNumber) \
|
V(ToNumber) \
|
||||||
|
V(ToObject) \
|
||||||
V(VectorStoreICTrampoline) \
|
V(VectorStoreICTrampoline) \
|
||||||
V(VectorKeyedStoreICTrampoline) \
|
V(VectorKeyedStoreICTrampoline) \
|
||||||
V(VectorStoreIC) \
|
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 {
|
class StringCompareStub : public PlatformCodeStub {
|
||||||
public:
|
public:
|
||||||
explicit StringCompareStub(Isolate* isolate) : PlatformCodeStub(isolate) {}
|
explicit StringCompareStub(Isolate* isolate) : PlatformCodeStub(isolate) {}
|
||||||
|
@ -268,7 +268,7 @@ function SetForEach(f, receiver) {
|
|||||||
while (%SetIteratorNext(iterator, value_array)) {
|
while (%SetIteratorNext(iterator, value_array)) {
|
||||||
if (stepping) %DebugPrepareStepInIfStepping(f);
|
if (stepping) %DebugPrepareStepInIfStepping(f);
|
||||||
key = value_array[0];
|
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);
|
%_CallFunction(new_receiver, key, key, this, f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -457,7 +457,7 @@ function MapForEach(f, receiver) {
|
|||||||
var value_array = [UNDEFINED, UNDEFINED];
|
var value_array = [UNDEFINED, UNDEFINED];
|
||||||
while (%MapIteratorNext(iterator, value_array)) {
|
while (%MapIteratorNext(iterator, value_array)) {
|
||||||
if (stepping) %DebugPrepareStepInIfStepping(f);
|
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);
|
%_CallFunction(new_receiver, value_array[1], value_array[0], this, f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -307,7 +307,9 @@ void JSGenericLowering::LowerJSToName(Node* node) {
|
|||||||
|
|
||||||
|
|
||||||
void JSGenericLowering::LowerJSToObject(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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -94,6 +94,8 @@ Reduction JSIntrinsicLowering::Reduce(Node* node) {
|
|||||||
return ReduceGetTypeFeedbackVector(node);
|
return ReduceGetTypeFeedbackVector(node);
|
||||||
case Runtime::kInlineGetCallerJSFunction:
|
case Runtime::kInlineGetCallerJSFunction:
|
||||||
return ReduceGetCallerJSFunction(node);
|
return ReduceGetCallerJSFunction(node);
|
||||||
|
case Runtime::kInlineToObject:
|
||||||
|
return ReduceToObject(node);
|
||||||
case Runtime::kInlineThrowNotDateError:
|
case Runtime::kInlineThrowNotDateError:
|
||||||
return ReduceThrowNotDateError(node);
|
return ReduceThrowNotDateError(node);
|
||||||
case Runtime::kInlineCallFunction:
|
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) {
|
Reduction JSIntrinsicLowering::ReduceCallFunction(Node* node) {
|
||||||
CallRuntimeParameters params = OpParameter<CallRuntimeParameters>(node->op());
|
CallRuntimeParameters params = OpParameter<CallRuntimeParameters>(node->op());
|
||||||
size_t arity = params.arity();
|
size_t arity = params.arity();
|
||||||
|
@ -58,6 +58,7 @@ class JSIntrinsicLowering final : public AdvancedReducer {
|
|||||||
Reduction ReduceGetTypeFeedbackVector(Node* node);
|
Reduction ReduceGetTypeFeedbackVector(Node* node);
|
||||||
Reduction ReduceGetCallerJSFunction(Node* node);
|
Reduction ReduceGetCallerJSFunction(Node* node);
|
||||||
Reduction ReduceThrowNotDateError(Node* node);
|
Reduction ReduceThrowNotDateError(Node* node);
|
||||||
|
Reduction ReduceToObject(Node* node);
|
||||||
Reduction ReduceCallFunction(Node* node);
|
Reduction ReduceCallFunction(Node* node);
|
||||||
|
|
||||||
Reduction Change(Node* node, const Operator* op);
|
Reduction Change(Node* node, const Operator* op);
|
||||||
|
@ -219,6 +219,7 @@ int Linkage::FrameStateInputCount(Runtime::FunctionId function) {
|
|||||||
case Runtime::kInlineGetCallerJSFunction:
|
case Runtime::kInlineGetCallerJSFunction:
|
||||||
case Runtime::kInlineGetPrototype:
|
case Runtime::kInlineGetPrototype:
|
||||||
case Runtime::kInlineRegExpExec:
|
case Runtime::kInlineRegExpExec:
|
||||||
|
case Runtime::kInlineToObject:
|
||||||
return 1;
|
return 1;
|
||||||
case Runtime::kInlineDeoptimizeNow:
|
case Runtime::kInlineDeoptimizeNow:
|
||||||
case Runtime::kInlineThrowNotDateError:
|
case Runtime::kInlineThrowNotDateError:
|
||||||
|
@ -1559,6 +1559,8 @@ Bounds Typer::Visitor::TypeJSCallRuntime(Node* node) {
|
|||||||
return Bounds(Type::None(), Type::Range(0, 32, zone()));
|
return Bounds(Type::None(), Type::Range(0, 32, zone()));
|
||||||
case Runtime::kInlineStringGetLength:
|
case Runtime::kInlineStringGetLength:
|
||||||
return Bounds(Type::None(), Type::Range(0, String::kMaxLength, zone()));
|
return Bounds(Type::None(), Type::Range(0, String::kMaxLength, zone()));
|
||||||
|
case Runtime::kInlineToObject:
|
||||||
|
return Bounds(Type::None(), Type::Receiver());
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -97,7 +97,6 @@ enum BindingFlags {
|
|||||||
V(TO_NUMBER_FUN_INDEX, JSFunction, to_number_fun) \
|
V(TO_NUMBER_FUN_INDEX, JSFunction, to_number_fun) \
|
||||||
V(TO_STRING_FUN_INDEX, JSFunction, to_string_fun) \
|
V(TO_STRING_FUN_INDEX, JSFunction, to_string_fun) \
|
||||||
V(TO_DETAIL_STRING_FUN_INDEX, JSFunction, to_detail_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_INTEGER_FUN_INDEX, JSFunction, to_integer_fun) \
|
||||||
V(TO_UINT32_FUN_INDEX, JSFunction, to_uint32_fun) \
|
V(TO_UINT32_FUN_INDEX, JSFunction, to_uint32_fun) \
|
||||||
V(TO_INT32_FUN_INDEX, JSFunction, to_int32_fun) \
|
V(TO_INT32_FUN_INDEX, JSFunction, to_int32_fun) \
|
||||||
@ -363,7 +362,6 @@ class Context: public FixedArray {
|
|||||||
TO_NUMBER_FUN_INDEX,
|
TO_NUMBER_FUN_INDEX,
|
||||||
TO_STRING_FUN_INDEX,
|
TO_STRING_FUN_INDEX,
|
||||||
TO_DETAIL_STRING_FUN_INDEX,
|
TO_DETAIL_STRING_FUN_INDEX,
|
||||||
TO_OBJECT_FUN_INDEX,
|
|
||||||
TO_INTEGER_FUN_INDEX,
|
TO_INTEGER_FUN_INDEX,
|
||||||
TO_UINT32_FUN_INDEX,
|
TO_UINT32_FUN_INDEX,
|
||||||
TO_INT32_FUN_INDEX,
|
TO_INT32_FUN_INDEX,
|
||||||
|
@ -775,7 +775,7 @@ function DateToISOString() {
|
|||||||
|
|
||||||
|
|
||||||
function DateToJSON(key) {
|
function DateToJSON(key) {
|
||||||
var o = $toObject(this);
|
var o = TO_OBJECT(this);
|
||||||
var tv = $defaultNumber(o);
|
var tv = $defaultNumber(o);
|
||||||
if (IS_NUMBER(tv) && !NUMBER_IS_FINITE(tv)) {
|
if (IS_NUMBER(tv) && !NUMBER_IS_FINITE(tv)) {
|
||||||
return null;
|
return null;
|
||||||
|
@ -385,7 +385,8 @@ class OptimizedFunctionVisitor BASE_EMBEDDED {
|
|||||||
V(kValueMismatch, "value mismatch") \
|
V(kValueMismatch, "value mismatch") \
|
||||||
V(kWrongInstanceType, "wrong instance type") \
|
V(kWrongInstanceType, "wrong instance type") \
|
||||||
V(kWrongMap, "wrong map") \
|
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 {
|
class Deoptimizer : public Malloced {
|
||||||
|
@ -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(
|
MaybeHandle<Object> Execution::ToInteger(
|
||||||
Isolate* isolate, Handle<Object> obj) {
|
Isolate* isolate, Handle<Object> obj) {
|
||||||
RETURN_NATIVE_CALL(to_integer, { obj });
|
RETURN_NATIVE_CALL(to_integer, { obj });
|
||||||
@ -589,6 +581,16 @@ MaybeHandle<Object> Execution::NewDate(Isolate* isolate, double time) {
|
|||||||
#undef RETURN_NATIVE_CALL
|
#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,
|
MaybeHandle<JSRegExp> Execution::NewJSRegExp(Handle<String> pattern,
|
||||||
Handle<String> flags) {
|
Handle<String> flags) {
|
||||||
Isolate* isolate = pattern->GetIsolate();
|
Isolate* isolate = pattern->GetIsolate();
|
||||||
|
@ -1083,8 +1083,8 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
|
|||||||
__ CompareObjectType(r0, r1, r1, FIRST_SPEC_OBJECT_TYPE);
|
__ CompareObjectType(r0, r1, r1, FIRST_SPEC_OBJECT_TYPE);
|
||||||
__ b(ge, &done_convert);
|
__ b(ge, &done_convert);
|
||||||
__ bind(&convert);
|
__ bind(&convert);
|
||||||
__ push(r0);
|
ToObjectStub stub(isolate());
|
||||||
__ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
|
__ CallStub(&stub);
|
||||||
__ bind(&done_convert);
|
__ bind(&done_convert);
|
||||||
PrepareForBailoutForId(stmt->ToObjectId(), TOS_REG);
|
PrepareForBailoutForId(stmt->ToObjectId(), TOS_REG);
|
||||||
__ push(r0);
|
__ 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) {
|
void FullCodeGenerator::EmitStringCharFromCode(CallRuntime* expr) {
|
||||||
ZoneList<Expression*>* args = expr->arguments();
|
ZoneList<Expression*>* args = expr->arguments();
|
||||||
DCHECK(args->length() == 1);
|
DCHECK(args->length() == 1);
|
||||||
|
@ -1085,8 +1085,8 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
|
|||||||
__ JumpIfSmi(x0, &convert);
|
__ JumpIfSmi(x0, &convert);
|
||||||
__ JumpIfObjectType(x0, x10, x11, FIRST_SPEC_OBJECT_TYPE, &done_convert, ge);
|
__ JumpIfObjectType(x0, x10, x11, FIRST_SPEC_OBJECT_TYPE, &done_convert, ge);
|
||||||
__ Bind(&convert);
|
__ Bind(&convert);
|
||||||
__ Push(x0);
|
ToObjectStub stub(isolate());
|
||||||
__ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
|
__ CallStub(&stub);
|
||||||
__ Bind(&done_convert);
|
__ Bind(&done_convert);
|
||||||
PrepareForBailoutForId(stmt->ToObjectId(), TOS_REG);
|
PrepareForBailoutForId(stmt->ToObjectId(), TOS_REG);
|
||||||
__ Push(x0);
|
__ 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) {
|
void FullCodeGenerator::EmitStringCharFromCode(CallRuntime* expr) {
|
||||||
ZoneList<Expression*>* args = expr->arguments();
|
ZoneList<Expression*>* args = expr->arguments();
|
||||||
DCHECK(args->length() == 1);
|
DCHECK(args->length() == 1);
|
||||||
|
@ -531,6 +531,7 @@ class FullCodeGenerator: public AstVisitor {
|
|||||||
F(RegExpConstructResult) \
|
F(RegExpConstructResult) \
|
||||||
F(GetFromCache) \
|
F(GetFromCache) \
|
||||||
F(NumberToString) \
|
F(NumberToString) \
|
||||||
|
F(ToObject) \
|
||||||
F(DebugIsActive)
|
F(DebugIsActive)
|
||||||
|
|
||||||
#define GENERATOR_DECLARATION(Name) void Emit##Name(CallRuntime* call);
|
#define GENERATOR_DECLARATION(Name) void Emit##Name(CallRuntime* call);
|
||||||
|
@ -1025,8 +1025,8 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
|
|||||||
__ CmpObjectType(eax, FIRST_SPEC_OBJECT_TYPE, ecx);
|
__ CmpObjectType(eax, FIRST_SPEC_OBJECT_TYPE, ecx);
|
||||||
__ j(above_equal, &done_convert, Label::kNear);
|
__ j(above_equal, &done_convert, Label::kNear);
|
||||||
__ bind(&convert);
|
__ bind(&convert);
|
||||||
__ push(eax);
|
ToObjectStub stub(isolate());
|
||||||
__ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
|
__ CallStub(&stub);
|
||||||
__ bind(&done_convert);
|
__ bind(&done_convert);
|
||||||
PrepareForBailoutForId(stmt->ToObjectId(), TOS_REG);
|
PrepareForBailoutForId(stmt->ToObjectId(), TOS_REG);
|
||||||
__ push(eax);
|
__ 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) {
|
void FullCodeGenerator::EmitStringCharFromCode(CallRuntime* expr) {
|
||||||
ZoneList<Expression*>* args = expr->arguments();
|
ZoneList<Expression*>* args = expr->arguments();
|
||||||
DCHECK(args->length() == 1);
|
DCHECK(args->length() == 1);
|
||||||
|
@ -1085,8 +1085,8 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
|
|||||||
__ GetObjectType(a0, a1, a1);
|
__ GetObjectType(a0, a1, a1);
|
||||||
__ Branch(&done_convert, ge, a1, Operand(FIRST_SPEC_OBJECT_TYPE));
|
__ Branch(&done_convert, ge, a1, Operand(FIRST_SPEC_OBJECT_TYPE));
|
||||||
__ bind(&convert);
|
__ bind(&convert);
|
||||||
__ push(a0);
|
ToObjectStub stub(isolate());
|
||||||
__ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
|
__ CallStub(&stub);
|
||||||
__ mov(a0, v0);
|
__ mov(a0, v0);
|
||||||
__ bind(&done_convert);
|
__ bind(&done_convert);
|
||||||
PrepareForBailoutForId(stmt->ToObjectId(), TOS_REG);
|
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) {
|
void FullCodeGenerator::EmitStringCharFromCode(CallRuntime* expr) {
|
||||||
ZoneList<Expression*>* args = expr->arguments();
|
ZoneList<Expression*>* args = expr->arguments();
|
||||||
DCHECK(args->length() == 1);
|
DCHECK(args->length() == 1);
|
||||||
|
@ -1082,8 +1082,8 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
|
|||||||
__ GetObjectType(a0, a1, a1);
|
__ GetObjectType(a0, a1, a1);
|
||||||
__ Branch(&done_convert, ge, a1, Operand(FIRST_SPEC_OBJECT_TYPE));
|
__ Branch(&done_convert, ge, a1, Operand(FIRST_SPEC_OBJECT_TYPE));
|
||||||
__ bind(&convert);
|
__ bind(&convert);
|
||||||
__ push(a0);
|
ToObjectStub stub(isolate());
|
||||||
__ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
|
__ CallStub(&stub);
|
||||||
__ mov(a0, v0);
|
__ mov(a0, v0);
|
||||||
__ bind(&done_convert);
|
__ bind(&done_convert);
|
||||||
PrepareForBailoutForId(stmt->ToObjectId(), TOS_REG);
|
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) {
|
void FullCodeGenerator::EmitStringCharFromCode(CallRuntime* expr) {
|
||||||
ZoneList<Expression*>* args = expr->arguments();
|
ZoneList<Expression*>* args = expr->arguments();
|
||||||
DCHECK(args->length() == 1);
|
DCHECK(args->length() == 1);
|
||||||
|
@ -1046,8 +1046,8 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
|
|||||||
__ CompareObjectType(r3, r4, r4, FIRST_SPEC_OBJECT_TYPE);
|
__ CompareObjectType(r3, r4, r4, FIRST_SPEC_OBJECT_TYPE);
|
||||||
__ bge(&done_convert);
|
__ bge(&done_convert);
|
||||||
__ bind(&convert);
|
__ bind(&convert);
|
||||||
__ push(r3);
|
ToObjectStub stub(isolate());
|
||||||
__ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
|
__ CallStub(&stub);
|
||||||
__ bind(&done_convert);
|
__ bind(&done_convert);
|
||||||
PrepareForBailoutForId(stmt->ToObjectId(), TOS_REG);
|
PrepareForBailoutForId(stmt->ToObjectId(), TOS_REG);
|
||||||
__ push(r3);
|
__ 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) {
|
void FullCodeGenerator::EmitStringCharFromCode(CallRuntime* expr) {
|
||||||
ZoneList<Expression*>* args = expr->arguments();
|
ZoneList<Expression*>* args = expr->arguments();
|
||||||
DCHECK(args->length() == 1);
|
DCHECK(args->length() == 1);
|
||||||
|
@ -1039,12 +1039,12 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
|
|||||||
|
|
||||||
// Convert the object to a JS object.
|
// Convert the object to a JS object.
|
||||||
Label convert, done_convert;
|
Label convert, done_convert;
|
||||||
__ JumpIfSmi(rax, &convert);
|
__ JumpIfSmi(rax, &convert, Label::kNear);
|
||||||
__ CmpObjectType(rax, FIRST_SPEC_OBJECT_TYPE, rcx);
|
__ CmpObjectType(rax, FIRST_SPEC_OBJECT_TYPE, rcx);
|
||||||
__ j(above_equal, &done_convert);
|
__ j(above_equal, &done_convert, Label::kNear);
|
||||||
__ bind(&convert);
|
__ bind(&convert);
|
||||||
__ Push(rax);
|
ToObjectStub stub(isolate());
|
||||||
__ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
|
__ CallStub(&stub);
|
||||||
__ bind(&done_convert);
|
__ bind(&done_convert);
|
||||||
PrepareForBailoutForId(stmt->ToObjectId(), TOS_REG);
|
PrepareForBailoutForId(stmt->ToObjectId(), TOS_REG);
|
||||||
__ Push(rax);
|
__ 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) {
|
void FullCodeGenerator::EmitStringCharFromCode(CallRuntime* expr) {
|
||||||
ZoneList<Expression*>* args = expr->arguments();
|
ZoneList<Expression*>* args = expr->arguments();
|
||||||
DCHECK(args->length() == 1);
|
DCHECK(args->length() == 1);
|
||||||
|
@ -1018,8 +1018,8 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
|
|||||||
__ CmpObjectType(eax, FIRST_SPEC_OBJECT_TYPE, ecx);
|
__ CmpObjectType(eax, FIRST_SPEC_OBJECT_TYPE, ecx);
|
||||||
__ j(above_equal, &done_convert, Label::kNear);
|
__ j(above_equal, &done_convert, Label::kNear);
|
||||||
__ bind(&convert);
|
__ bind(&convert);
|
||||||
__ push(eax);
|
ToObjectStub stub(isolate());
|
||||||
__ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
|
__ CallStub(&stub);
|
||||||
__ bind(&done_convert);
|
__ bind(&done_convert);
|
||||||
PrepareForBailoutForId(stmt->ToObjectId(), TOS_REG);
|
PrepareForBailoutForId(stmt->ToObjectId(), TOS_REG);
|
||||||
__ push(eax);
|
__ 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) {
|
void FullCodeGenerator::EmitStringCharFromCode(CallRuntime* expr) {
|
||||||
ZoneList<Expression*>* args = expr->arguments();
|
ZoneList<Expression*>* args = expr->arguments();
|
||||||
DCHECK(args->length() == 1);
|
DCHECK(args->length() == 1);
|
||||||
|
@ -16,7 +16,7 @@ var GlobalArray = global.Array;
|
|||||||
// https://github.com/tc39/Array.prototype.includes
|
// https://github.com/tc39/Array.prototype.includes
|
||||||
// 6e3b78c927aeda20b9d40e81303f9d44596cd904
|
// 6e3b78c927aeda20b9d40e81303f9d44596cd904
|
||||||
function ArrayIncludes(searchElement, fromIndex) {
|
function ArrayIncludes(searchElement, fromIndex) {
|
||||||
var array = $toObject(this);
|
var array = TO_OBJECT(this);
|
||||||
var len = $toLength(array.length);
|
var len = $toLength(array.length);
|
||||||
|
|
||||||
if (len === 0) {
|
if (len === 0) {
|
||||||
|
@ -83,7 +83,7 @@ function InnerArrayCopyWithin(target, start, end, array, length) {
|
|||||||
function ArrayCopyWithin(target, start, end) {
|
function ArrayCopyWithin(target, start, end) {
|
||||||
CHECK_OBJECT_COERCIBLE(this, "Array.prototype.copyWithin");
|
CHECK_OBJECT_COERCIBLE(this, "Array.prototype.copyWithin");
|
||||||
|
|
||||||
var array = TO_OBJECT_INLINE(this);
|
var array = TO_OBJECT(this);
|
||||||
var length = $toLength(array.length);
|
var length = $toLength(array.length);
|
||||||
|
|
||||||
return InnerArrayCopyWithin(target, start, end, 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++) {
|
for (var i = 0; i < length; i++) {
|
||||||
var element = array[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)) {
|
if (%_CallFunction(newThisArg, element, i, array, predicate)) {
|
||||||
return element;
|
return element;
|
||||||
}
|
}
|
||||||
@ -116,7 +116,7 @@ function InnerArrayFind(predicate, thisArg, array, length) {
|
|||||||
function ArrayFind(predicate, thisArg) {
|
function ArrayFind(predicate, thisArg) {
|
||||||
CHECK_OBJECT_COERCIBLE(this, "Array.prototype.find");
|
CHECK_OBJECT_COERCIBLE(this, "Array.prototype.find");
|
||||||
|
|
||||||
var array = $toObject(this);
|
var array = TO_OBJECT(this);
|
||||||
var length = $toInteger(array.length);
|
var length = $toInteger(array.length);
|
||||||
|
|
||||||
return InnerArrayFind(predicate, thisArg, 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++) {
|
for (var i = 0; i < length; i++) {
|
||||||
var element = array[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)) {
|
if (%_CallFunction(newThisArg, element, i, array, predicate)) {
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
@ -149,7 +149,7 @@ function InnerArrayFindIndex(predicate, thisArg, array, length) {
|
|||||||
function ArrayFindIndex(predicate, thisArg) {
|
function ArrayFindIndex(predicate, thisArg) {
|
||||||
CHECK_OBJECT_COERCIBLE(this, "Array.prototype.findIndex");
|
CHECK_OBJECT_COERCIBLE(this, "Array.prototype.findIndex");
|
||||||
|
|
||||||
var array = $toObject(this);
|
var array = TO_OBJECT(this);
|
||||||
var length = $toInteger(array.length);
|
var length = $toInteger(array.length);
|
||||||
|
|
||||||
return InnerArrayFindIndex(predicate, thisArg, array, length);
|
return InnerArrayFindIndex(predicate, thisArg, array, length);
|
||||||
@ -187,7 +187,7 @@ function InnerArrayFill(value, start, end, array, length) {
|
|||||||
function ArrayFill(value, start, end) {
|
function ArrayFill(value, start, end) {
|
||||||
CHECK_OBJECT_COERCIBLE(this, "Array.prototype.fill");
|
CHECK_OBJECT_COERCIBLE(this, "Array.prototype.fill");
|
||||||
|
|
||||||
var array = $toObject(this);
|
var array = TO_OBJECT(this);
|
||||||
var length = TO_UINT32(array.length);
|
var length = TO_UINT32(array.length);
|
||||||
|
|
||||||
return InnerArrayFill(value, start, end, 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
|
// ES6, draft 10-14-14, section 22.1.2.1
|
||||||
function ArrayFrom(arrayLike, mapfn, receiver) {
|
function ArrayFrom(arrayLike, mapfn, receiver) {
|
||||||
var items = $toObject(arrayLike);
|
var items = TO_OBJECT(arrayLike);
|
||||||
var mapping = !IS_UNDEFINED(mapfn);
|
var mapping = !IS_UNDEFINED(mapfn);
|
||||||
|
|
||||||
if (mapping) {
|
if (mapping) {
|
||||||
@ -215,7 +215,7 @@ function ArrayFrom(arrayLike, mapfn, receiver) {
|
|||||||
if (IS_NULL(receiver)) {
|
if (IS_NULL(receiver)) {
|
||||||
receiver = UNDEFINED;
|
receiver = UNDEFINED;
|
||||||
} else if (!IS_UNDEFINED(receiver)) {
|
} else if (!IS_UNDEFINED(receiver)) {
|
||||||
receiver = TO_OBJECT_INLINE(receiver);
|
receiver = TO_OBJECT(receiver);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -24,7 +24,7 @@ utils.Import(function(from) {
|
|||||||
|
|
||||||
// ES6, draft 04-03-15, section 19.1.2.1
|
// ES6, draft 04-03-15, section 19.1.2.1
|
||||||
function ObjectAssign(target, sources) {
|
function ObjectAssign(target, sources) {
|
||||||
var to = TO_OBJECT_INLINE(target);
|
var to = TO_OBJECT(target);
|
||||||
var argsLen = %_ArgumentsLength();
|
var argsLen = %_ArgumentsLength();
|
||||||
if (argsLen < 2) return to;
|
if (argsLen < 2) return to;
|
||||||
|
|
||||||
@ -34,7 +34,7 @@ function ObjectAssign(target, sources) {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
var from = TO_OBJECT_INLINE(nextSource);
|
var from = TO_OBJECT(nextSource);
|
||||||
var keys = OwnPropertyKeys(from);
|
var keys = OwnPropertyKeys(from);
|
||||||
var len = keys.length;
|
var len = keys.length;
|
||||||
|
|
||||||
|
159
src/hydrogen.cc
159
src/hydrogen.cc
@ -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(
|
HAllocate* HGraphBuilder::BuildAllocate(
|
||||||
HValue* object_size,
|
HValue* object_size,
|
||||||
HType type,
|
HType type,
|
||||||
|
@ -1329,6 +1329,7 @@ class HGraphBuilder {
|
|||||||
bool is_jsarray);
|
bool is_jsarray);
|
||||||
|
|
||||||
HValue* BuildNumberToString(HValue* object, Type* type);
|
HValue* BuildNumberToString(HValue* object, Type* type);
|
||||||
|
HValue* BuildToObject(HValue* receiver);
|
||||||
|
|
||||||
void BuildJSObjectCheck(HValue* receiver,
|
void BuildJSObjectCheck(HValue* receiver,
|
||||||
int bit_field_mask);
|
int bit_field_mask);
|
||||||
|
14
src/i18n.js
14
src/i18n.js
@ -251,7 +251,7 @@ function supportedLocalesOf(service, locales, options) {
|
|||||||
if (IS_UNDEFINED(options)) {
|
if (IS_UNDEFINED(options)) {
|
||||||
options = {};
|
options = {};
|
||||||
} else {
|
} else {
|
||||||
options = $toObject(options);
|
options = TO_OBJECT(options);
|
||||||
}
|
}
|
||||||
|
|
||||||
var matcher = options.localeMatcher;
|
var matcher = options.localeMatcher;
|
||||||
@ -717,7 +717,7 @@ function initializeLocaleList(locales) {
|
|||||||
return freezeArray(seen);
|
return freezeArray(seen);
|
||||||
}
|
}
|
||||||
|
|
||||||
var o = $toObject(locales);
|
var o = TO_OBJECT(locales);
|
||||||
var len = TO_UINT32(o.length);
|
var len = TO_UINT32(o.length);
|
||||||
|
|
||||||
for (var k = 0; k < len; k++) {
|
for (var k = 0; k < len; k++) {
|
||||||
@ -951,7 +951,7 @@ function initializeCollator(collator, locales, options) {
|
|||||||
return new Intl.Collator(locales, options);
|
return new Intl.Collator(locales, options);
|
||||||
}
|
}
|
||||||
|
|
||||||
return initializeCollator($toObject(this), locales, options);
|
return initializeCollator(TO_OBJECT(this), locales, options);
|
||||||
},
|
},
|
||||||
DONT_ENUM
|
DONT_ENUM
|
||||||
);
|
);
|
||||||
@ -1192,7 +1192,7 @@ function initializeNumberFormat(numberFormat, locales, options) {
|
|||||||
return new Intl.NumberFormat(locales, options);
|
return new Intl.NumberFormat(locales, options);
|
||||||
}
|
}
|
||||||
|
|
||||||
return initializeNumberFormat($toObject(this), locales, options);
|
return initializeNumberFormat(TO_OBJECT(this), locales, options);
|
||||||
},
|
},
|
||||||
DONT_ENUM
|
DONT_ENUM
|
||||||
);
|
);
|
||||||
@ -1444,7 +1444,7 @@ function toDateTimeOptions(options, required, defaults) {
|
|||||||
if (IS_UNDEFINED(options)) {
|
if (IS_UNDEFINED(options)) {
|
||||||
options = {};
|
options = {};
|
||||||
} else {
|
} else {
|
||||||
options = TO_OBJECT_INLINE(options);
|
options = TO_OBJECT(options);
|
||||||
}
|
}
|
||||||
|
|
||||||
var needsDefault = true;
|
var needsDefault = true;
|
||||||
@ -1594,7 +1594,7 @@ function initializeDateTimeFormat(dateFormat, locales, options) {
|
|||||||
return new Intl.DateTimeFormat(locales, options);
|
return new Intl.DateTimeFormat(locales, options);
|
||||||
}
|
}
|
||||||
|
|
||||||
return initializeDateTimeFormat($toObject(this), locales, options);
|
return initializeDateTimeFormat(TO_OBJECT(this), locales, options);
|
||||||
},
|
},
|
||||||
DONT_ENUM
|
DONT_ENUM
|
||||||
);
|
);
|
||||||
@ -1814,7 +1814,7 @@ function initializeBreakIterator(iterator, locales, options) {
|
|||||||
return new Intl.v8BreakIterator(locales, options);
|
return new Intl.v8BreakIterator(locales, options);
|
||||||
}
|
}
|
||||||
|
|
||||||
return initializeBreakIterator($toObject(this), locales, options);
|
return initializeBreakIterator(TO_OBJECT(this), locales, options);
|
||||||
},
|
},
|
||||||
DONT_ENUM
|
DONT_ENUM
|
||||||
);
|
);
|
||||||
|
@ -994,8 +994,9 @@ void Builtins::Generate_FunctionCall(MacroAssembler* masm) {
|
|||||||
__ SmiTag(eax);
|
__ SmiTag(eax);
|
||||||
__ push(eax);
|
__ push(eax);
|
||||||
|
|
||||||
__ push(ebx);
|
__ mov(eax, ebx);
|
||||||
__ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
|
ToObjectStub stub(masm->isolate());
|
||||||
|
__ CallStub(&stub);
|
||||||
__ mov(ebx, eax);
|
__ mov(ebx, eax);
|
||||||
__ Move(edx, Immediate(0)); // restore
|
__ Move(edx, Immediate(0)); // restore
|
||||||
|
|
||||||
@ -1215,8 +1216,9 @@ static void Generate_ApplyHelper(MacroAssembler* masm, bool targetIsArgument) {
|
|||||||
__ j(above_equal, &push_receiver);
|
__ j(above_equal, &push_receiver);
|
||||||
|
|
||||||
__ bind(&call_to_object);
|
__ bind(&call_to_object);
|
||||||
__ push(ebx);
|
__ mov(eax, ebx);
|
||||||
__ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
|
ToObjectStub stub(masm->isolate());
|
||||||
|
__ CallStub(&stub);
|
||||||
__ mov(ebx, eax);
|
__ mov(ebx, eax);
|
||||||
__ jmp(&push_receiver);
|
__ jmp(&push_receiver);
|
||||||
|
|
||||||
|
@ -2093,8 +2093,8 @@ static void EmitWrapCase(MacroAssembler* masm, int argc, Label* cont) {
|
|||||||
// Wrap the receiver and patch it back onto the stack.
|
// Wrap the receiver and patch it back onto the stack.
|
||||||
{ FrameScope frame_scope(masm, StackFrame::INTERNAL);
|
{ FrameScope frame_scope(masm, StackFrame::INTERNAL);
|
||||||
__ push(edi);
|
__ push(edi);
|
||||||
__ push(eax);
|
ToObjectStub stub(masm->isolate());
|
||||||
__ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
|
__ CallStub(&stub);
|
||||||
__ pop(edi);
|
__ pop(edi);
|
||||||
}
|
}
|
||||||
__ mov(Operand(esp, (argc + 1) * kPointerSize), eax);
|
__ mov(Operand(esp, (argc + 1) * kPointerSize), eax);
|
||||||
|
@ -103,6 +103,10 @@ void ToNumberDescriptor::InitializePlatformSpecific(
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// static
|
||||||
|
const Register ToObjectDescriptor::ReceiverRegister() { return eax; }
|
||||||
|
|
||||||
|
|
||||||
void NumberToStringDescriptor::InitializePlatformSpecific(
|
void NumberToStringDescriptor::InitializePlatformSpecific(
|
||||||
CallInterfaceDescriptorData* data) {
|
CallInterfaceDescriptorData* data) {
|
||||||
Register registers[] = {eax};
|
Register registers[] = {eax};
|
||||||
|
@ -155,6 +155,13 @@ void InstanceofDescriptor::InitializePlatformSpecific(
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void ToObjectDescriptor::InitializePlatformSpecific(
|
||||||
|
CallInterfaceDescriptorData* data) {
|
||||||
|
Register registers[] = {ReceiverRegister()};
|
||||||
|
data->InitializePlatformSpecific(arraysize(registers), registers);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void MathPowTaggedDescriptor::InitializePlatformSpecific(
|
void MathPowTaggedDescriptor::InitializePlatformSpecific(
|
||||||
CallInterfaceDescriptorData* data) {
|
CallInterfaceDescriptorData* data) {
|
||||||
Register registers[] = {exponent()};
|
Register registers[] = {exponent()};
|
||||||
|
@ -24,6 +24,7 @@ class PlatformInterfaceDescriptor;
|
|||||||
V(FastNewClosure) \
|
V(FastNewClosure) \
|
||||||
V(FastNewContext) \
|
V(FastNewContext) \
|
||||||
V(ToNumber) \
|
V(ToNumber) \
|
||||||
|
V(ToObject) \
|
||||||
V(NumberToString) \
|
V(NumberToString) \
|
||||||
V(Typeof) \
|
V(Typeof) \
|
||||||
V(FastCloneShallowArray) \
|
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 {
|
class NumberToStringDescriptor : public CallInterfaceDescriptor {
|
||||||
public:
|
public:
|
||||||
DECLARE_DESCRIPTOR(NumberToStringDescriptor, CallInterfaceDescriptor)
|
DECLARE_DESCRIPTOR(NumberToStringDescriptor, CallInterfaceDescriptor)
|
||||||
|
@ -154,7 +154,7 @@ macro TO_INT32(arg) = (%_IsSmi(%IS_VAR(arg)) ? arg : (arg >> 0));
|
|||||||
macro TO_UINT32(arg) = (arg >>> 0);
|
macro TO_UINT32(arg) = (arg >>> 0);
|
||||||
macro TO_STRING_INLINE(arg) = (IS_STRING(%IS_VAR(arg)) ? arg : $nonStringToString(arg));
|
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_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 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 HAS_OWN_PROPERTY(arg, index) = (%_CallFunction(arg, index, ObjectHasOwnProperty));
|
||||||
macro SHOULD_CREATE_WRAPPER(functionName, receiver) = (!IS_SPEC_OBJECT(receiver) && %IsSloppyModeFunction(functionName));
|
macro SHOULD_CREATE_WRAPPER(functionName, receiver) = (!IS_SPEC_OBJECT(receiver) && %IsSloppyModeFunction(functionName));
|
||||||
|
@ -67,7 +67,7 @@ var GlobalEvalError;
|
|||||||
function NoSideEffectsObjectToString() {
|
function NoSideEffectsObjectToString() {
|
||||||
if (IS_UNDEFINED(this) && !IS_UNDETECTABLE(this)) return "[object Undefined]";
|
if (IS_UNDEFINED(this) && !IS_UNDETECTABLE(this)) return "[object Undefined]";
|
||||||
if (IS_NULL(this)) return "[object Null]";
|
if (IS_NULL(this)) return "[object Null]";
|
||||||
return "[object " + %_ClassOf(TO_OBJECT_INLINE(this)) + "]";
|
return "[object " + %_ClassOf(TO_OBJECT(this)) + "]";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1313,8 +1313,10 @@ void Builtins::Generate_FunctionCall(MacroAssembler* masm) {
|
|||||||
{
|
{
|
||||||
FrameScope scope(masm, StackFrame::INTERNAL);
|
FrameScope scope(masm, StackFrame::INTERNAL);
|
||||||
__ sll(a0, a0, kSmiTagSize); // Smi tagged.
|
__ sll(a0, a0, kSmiTagSize); // Smi tagged.
|
||||||
__ Push(a0, a2);
|
__ push(a0);
|
||||||
__ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
|
__ mov(a0, a2);
|
||||||
|
ToObjectStub stub(masm->isolate());
|
||||||
|
__ CallStub(&stub);
|
||||||
__ mov(a2, v0);
|
__ mov(a2, v0);
|
||||||
|
|
||||||
__ pop(a0);
|
__ pop(a0);
|
||||||
@ -1548,8 +1550,8 @@ static void Generate_ApplyHelper(MacroAssembler* masm, bool targetIsArgument) {
|
|||||||
// Convert the receiver to a regular object.
|
// Convert the receiver to a regular object.
|
||||||
// a0: receiver
|
// a0: receiver
|
||||||
__ bind(&call_to_object);
|
__ bind(&call_to_object);
|
||||||
__ push(a0);
|
ToObjectStub stub(masm->isolate());
|
||||||
__ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
|
__ CallStub(&stub);
|
||||||
__ mov(a0, v0); // Put object in a0 to match other paths to push_receiver.
|
__ mov(a0, v0); // Put object in a0 to match other paths to push_receiver.
|
||||||
__ Branch(&push_receiver);
|
__ Branch(&push_receiver);
|
||||||
|
|
||||||
|
@ -2675,8 +2675,10 @@ static void EmitSlowCase(MacroAssembler* masm,
|
|||||||
static void EmitWrapCase(MacroAssembler* masm, int argc, Label* cont) {
|
static void EmitWrapCase(MacroAssembler* masm, int argc, Label* cont) {
|
||||||
// Wrap the receiver and patch it back onto the stack.
|
// Wrap the receiver and patch it back onto the stack.
|
||||||
{ FrameScope frame_scope(masm, StackFrame::INTERNAL);
|
{ FrameScope frame_scope(masm, StackFrame::INTERNAL);
|
||||||
__ Push(a1, a3);
|
__ Push(a1);
|
||||||
__ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
|
__ mov(a0, a3);
|
||||||
|
ToObjectStub stub(masm->isolate());
|
||||||
|
__ CallStub(&stub);
|
||||||
__ pop(a1);
|
__ pop(a1);
|
||||||
}
|
}
|
||||||
__ Branch(USE_DELAY_SLOT, cont);
|
__ Branch(USE_DELAY_SLOT, cont);
|
||||||
|
@ -95,6 +95,10 @@ void ToNumberDescriptor::InitializePlatformSpecific(
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// static
|
||||||
|
const Register ToObjectDescriptor::ReceiverRegister() { return a0; }
|
||||||
|
|
||||||
|
|
||||||
void NumberToStringDescriptor::InitializePlatformSpecific(
|
void NumberToStringDescriptor::InitializePlatformSpecific(
|
||||||
CallInterfaceDescriptorData* data) {
|
CallInterfaceDescriptorData* data) {
|
||||||
Register registers[] = {a0};
|
Register registers[] = {a0};
|
||||||
|
@ -1309,8 +1309,10 @@ void Builtins::Generate_FunctionCall(MacroAssembler* masm) {
|
|||||||
{
|
{
|
||||||
FrameScope scope(masm, StackFrame::INTERNAL);
|
FrameScope scope(masm, StackFrame::INTERNAL);
|
||||||
__ SmiTag(a0);
|
__ SmiTag(a0);
|
||||||
__ Push(a0, a2);
|
__ Push(a0);
|
||||||
__ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
|
__ mov(a0, a2);
|
||||||
|
ToObjectStub stub(masm->isolate());
|
||||||
|
__ CallStub(&stub);
|
||||||
__ mov(a2, v0);
|
__ mov(a2, v0);
|
||||||
|
|
||||||
__ pop(a0);
|
__ pop(a0);
|
||||||
@ -1545,8 +1547,8 @@ static void Generate_ApplyHelper(MacroAssembler* masm, bool targetIsArgument) {
|
|||||||
// Convert the receiver to a regular object.
|
// Convert the receiver to a regular object.
|
||||||
// a0: receiver
|
// a0: receiver
|
||||||
__ bind(&call_to_object);
|
__ bind(&call_to_object);
|
||||||
__ push(a0);
|
ToObjectStub stub(masm->isolate());
|
||||||
__ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
|
__ CallStub(&stub);
|
||||||
__ mov(a0, v0); // Put object in a0 to match other paths to push_receiver.
|
__ mov(a0, v0); // Put object in a0 to match other paths to push_receiver.
|
||||||
__ Branch(&push_receiver);
|
__ Branch(&push_receiver);
|
||||||
|
|
||||||
|
@ -2714,8 +2714,10 @@ static void EmitSlowCase(MacroAssembler* masm,
|
|||||||
static void EmitWrapCase(MacroAssembler* masm, int argc, Label* cont) {
|
static void EmitWrapCase(MacroAssembler* masm, int argc, Label* cont) {
|
||||||
// Wrap the receiver and patch it back onto the stack.
|
// Wrap the receiver and patch it back onto the stack.
|
||||||
{ FrameScope frame_scope(masm, StackFrame::INTERNAL);
|
{ FrameScope frame_scope(masm, StackFrame::INTERNAL);
|
||||||
__ Push(a1, a3);
|
__ Push(a1);
|
||||||
__ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
|
__ mov(a0, a3);
|
||||||
|
ToObjectStub stub(masm->isolate());
|
||||||
|
__ CallStub(&stub);
|
||||||
__ pop(a1);
|
__ pop(a1);
|
||||||
}
|
}
|
||||||
__ Branch(USE_DELAY_SLOT, cont);
|
__ Branch(USE_DELAY_SLOT, cont);
|
||||||
|
@ -95,6 +95,10 @@ void ToNumberDescriptor::InitializePlatformSpecific(
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// static
|
||||||
|
const Register ToObjectDescriptor::ReceiverRegister() { return a0; }
|
||||||
|
|
||||||
|
|
||||||
void NumberToStringDescriptor::InitializePlatformSpecific(
|
void NumberToStringDescriptor::InitializePlatformSpecific(
|
||||||
CallInterfaceDescriptorData* data) {
|
CallInterfaceDescriptorData* data) {
|
||||||
Register registers[] = {a0};
|
Register registers[] = {a0};
|
||||||
|
@ -1338,8 +1338,10 @@ void Builtins::Generate_FunctionCall(MacroAssembler* masm) {
|
|||||||
// Enter an internal frame in order to preserve argument count.
|
// Enter an internal frame in order to preserve argument count.
|
||||||
FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL);
|
FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL);
|
||||||
__ SmiTag(r3);
|
__ SmiTag(r3);
|
||||||
__ Push(r3, r5);
|
__ Push(r3);
|
||||||
__ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
|
__ mr(r3, r5);
|
||||||
|
ToObjectStub stub(masm->isolate());
|
||||||
|
__ CallStub(&stub);
|
||||||
__ mr(r5, r3);
|
__ mr(r5, r3);
|
||||||
|
|
||||||
__ pop(r3);
|
__ pop(r3);
|
||||||
@ -1592,8 +1594,8 @@ static void Generate_ApplyHelper(MacroAssembler* masm, bool targetIsArgument) {
|
|||||||
// Convert the receiver to a regular object.
|
// Convert the receiver to a regular object.
|
||||||
// r3: receiver
|
// r3: receiver
|
||||||
__ bind(&call_to_object);
|
__ bind(&call_to_object);
|
||||||
__ push(r3);
|
ToObjectStub stub(masm->isolate());
|
||||||
__ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
|
__ CallStub(&stub);
|
||||||
__ b(&push_receiver);
|
__ b(&push_receiver);
|
||||||
|
|
||||||
__ bind(&use_global_proxy);
|
__ bind(&use_global_proxy);
|
||||||
|
@ -2726,8 +2726,10 @@ static void EmitWrapCase(MacroAssembler* masm, int argc, Label* cont) {
|
|||||||
// Wrap the receiver and patch it back onto the stack.
|
// Wrap the receiver and patch it back onto the stack.
|
||||||
{
|
{
|
||||||
FrameAndConstantPoolScope frame_scope(masm, StackFrame::INTERNAL);
|
FrameAndConstantPoolScope frame_scope(masm, StackFrame::INTERNAL);
|
||||||
__ Push(r4, r6);
|
__ push(r4);
|
||||||
__ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
|
__ mr(r3, r6);
|
||||||
|
ToObjectStub stub(masm->isolate());
|
||||||
|
__ CallStub(&stub);
|
||||||
__ pop(r4);
|
__ pop(r4);
|
||||||
}
|
}
|
||||||
__ StoreP(r3, MemOperand(sp, argc * kPointerSize), r0);
|
__ StoreP(r3, MemOperand(sp, argc * kPointerSize), r0);
|
||||||
|
@ -95,6 +95,10 @@ void ToNumberDescriptor::InitializePlatformSpecific(
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// static
|
||||||
|
const Register ToObjectDescriptor::ReceiverRegister() { return r3; }
|
||||||
|
|
||||||
|
|
||||||
void NumberToStringDescriptor::InitializePlatformSpecific(
|
void NumberToStringDescriptor::InitializePlatformSpecific(
|
||||||
CallInterfaceDescriptorData* data) {
|
CallInterfaceDescriptorData* data) {
|
||||||
Register registers[] = {r3};
|
Register registers[] = {r3};
|
||||||
|
@ -58,7 +58,6 @@ var APPLY_PREPARE;
|
|||||||
var REFLECT_APPLY_PREPARE;
|
var REFLECT_APPLY_PREPARE;
|
||||||
var REFLECT_CONSTRUCT_PREPARE;
|
var REFLECT_CONSTRUCT_PREPARE;
|
||||||
var STACK_OVERFLOW;
|
var STACK_OVERFLOW;
|
||||||
var TO_OBJECT;
|
|
||||||
var TO_NUMBER;
|
var TO_NUMBER;
|
||||||
var TO_STRING;
|
var TO_STRING;
|
||||||
var TO_NAME;
|
var TO_NAME;
|
||||||
@ -76,7 +75,6 @@ var $toInteger;
|
|||||||
var $toLength;
|
var $toLength;
|
||||||
var $toName;
|
var $toName;
|
||||||
var $toNumber;
|
var $toNumber;
|
||||||
var $toObject;
|
|
||||||
var $toPositiveInteger;
|
var $toPositiveInteger;
|
||||||
var $toPrimitive;
|
var $toPrimitive;
|
||||||
var $toString;
|
var $toString;
|
||||||
@ -512,7 +510,7 @@ SHR_STRONG = function SHR_STRONG(y) {
|
|||||||
|
|
||||||
// ECMA-262, section 11.4.1, page 46.
|
// ECMA-262, section 11.4.1, page 46.
|
||||||
DELETE = function DELETE(key, language_mode) {
|
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.
|
// Convert the receiver to a number - forward to ToNumber.
|
||||||
TO_NUMBER = function TO_NUMBER() {
|
TO_NUMBER = function TO_NUMBER() {
|
||||||
return %$toNumber(this);
|
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.
|
// ECMA-262, section 9.4, page 34.
|
||||||
function ToInteger(x) {
|
function ToInteger(x) {
|
||||||
if (%_IsSmi(x)) return x;
|
if (%_IsSmi(x)) return x;
|
||||||
@ -1006,7 +984,6 @@ $toInteger = ToInteger;
|
|||||||
$toLength = ToLength;
|
$toLength = ToLength;
|
||||||
$toName = ToName;
|
$toName = ToName;
|
||||||
$toNumber = ToNumber;
|
$toNumber = ToNumber;
|
||||||
$toObject = ToObject;
|
|
||||||
$toPositiveInteger = ToPositiveInteger;
|
$toPositiveInteger = ToPositiveInteger;
|
||||||
$toPrimitive = ToPrimitive;
|
$toPrimitive = ToPrimitive;
|
||||||
$toString = ToString;
|
$toString = ToString;
|
||||||
|
@ -1461,5 +1461,19 @@ RUNTIME_FUNCTION(Runtime_DefineSetterPropertyUnchecked) {
|
|||||||
setter, attrs));
|
setter, attrs));
|
||||||
return isolate->heap()->undefined_value();
|
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 internal
|
||||||
} // namespace v8
|
} // namespace v8
|
||||||
|
@ -33,14 +33,6 @@
|
|||||||
NumberTo##type##Component(*y), NumberTo##type##Component(*z)); \
|
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) \
|
#define SIMD_CHECK_FUNCTION(type) \
|
||||||
RUNTIME_FUNCTION(Runtime_##type##Check) { \
|
RUNTIME_FUNCTION(Runtime_##type##Check) { \
|
||||||
HandleScope scope(isolate); \
|
HandleScope scope(isolate); \
|
||||||
@ -101,7 +93,6 @@
|
|||||||
|
|
||||||
#define SIMD4_FUNCTIONS(type) \
|
#define SIMD4_FUNCTIONS(type) \
|
||||||
SIMD4_CREATE_FUNCTION(type) \
|
SIMD4_CREATE_FUNCTION(type) \
|
||||||
SIMD_CREATE_WRAPPER_FUNCTION(type) \
|
|
||||||
SIMD_CHECK_FUNCTION(type) \
|
SIMD_CHECK_FUNCTION(type) \
|
||||||
SIMD4_EXTRACT_LANE_FUNCTION(type) \
|
SIMD4_EXTRACT_LANE_FUNCTION(type) \
|
||||||
SIMD4_EQUALS_FUNCTION(type) \
|
SIMD4_EQUALS_FUNCTION(type) \
|
||||||
@ -125,5 +116,6 @@ inline bool Equals(float x, float y) { return x == y; }
|
|||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
SIMD4_FUNCTIONS(Float32x4)
|
SIMD4_FUNCTIONS(Float32x4)
|
||||||
}
|
|
||||||
} // namespace v8::internal
|
} // namespace internal
|
||||||
|
} // namespace v8
|
||||||
|
@ -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) {
|
RUNTIME_FUNCTION(Runtime_SymbolDescription) {
|
||||||
SealHandleScope shs(isolate);
|
SealHandleScope shs(isolate);
|
||||||
DCHECK(args.length() == 1);
|
DCHECK(args.length() == 1);
|
||||||
|
@ -497,7 +497,8 @@ namespace internal {
|
|||||||
F(IsStrong, 1, 1) \
|
F(IsStrong, 1, 1) \
|
||||||
F(ClassOf, 1, 1) \
|
F(ClassOf, 1, 1) \
|
||||||
F(DefineGetterPropertyUnchecked, 4, 1) \
|
F(DefineGetterPropertyUnchecked, 4, 1) \
|
||||||
F(DefineSetterPropertyUnchecked, 4, 1)
|
F(DefineSetterPropertyUnchecked, 4, 1) \
|
||||||
|
F(ToObject, 1, 1)
|
||||||
|
|
||||||
|
|
||||||
#define FOR_EACH_INTRINSIC_OBSERVE(F) \
|
#define FOR_EACH_INTRINSIC_OBSERVE(F) \
|
||||||
@ -570,7 +571,6 @@ namespace internal {
|
|||||||
|
|
||||||
#define FOR_EACH_INTRINSIC_SIMD(F) \
|
#define FOR_EACH_INTRINSIC_SIMD(F) \
|
||||||
F(CreateFloat32x4, 4, 1) \
|
F(CreateFloat32x4, 4, 1) \
|
||||||
F(NewFloat32x4Wrapper, 1, 1) \
|
|
||||||
F(Float32x4Check, 1, 1) \
|
F(Float32x4Check, 1, 1) \
|
||||||
F(Float32x4ExtractLane, 2, 1) \
|
F(Float32x4ExtractLane, 2, 1) \
|
||||||
F(Float32x4Equals, 2, 1) \
|
F(Float32x4Equals, 2, 1) \
|
||||||
@ -620,7 +620,6 @@ namespace internal {
|
|||||||
F(CreateSymbol, 1, 1) \
|
F(CreateSymbol, 1, 1) \
|
||||||
F(CreatePrivateSymbol, 1, 1) \
|
F(CreatePrivateSymbol, 1, 1) \
|
||||||
F(CreateGlobalPrivateSymbol, 1, 1) \
|
F(CreateGlobalPrivateSymbol, 1, 1) \
|
||||||
F(NewSymbolWrapper, 1, 1) \
|
|
||||||
F(SymbolDescription, 1, 1) \
|
F(SymbolDescription, 1, 1) \
|
||||||
F(SymbolRegistry, 0, 1) \
|
F(SymbolRegistry, 0, 1) \
|
||||||
F(SymbolIsPrivate, 1, 1)
|
F(SymbolIsPrivate, 1, 1)
|
||||||
|
@ -41,7 +41,7 @@ function CreateStringIterator(string) {
|
|||||||
|
|
||||||
// 21.1.5.2.1 %StringIteratorPrototype%.next( )
|
// 21.1.5.2.1 %StringIteratorPrototype%.next( )
|
||||||
function StringIteratorNext() {
|
function StringIteratorNext() {
|
||||||
var iterator = $toObject(this);
|
var iterator = TO_OBJECT(this);
|
||||||
|
|
||||||
if (!HAS_DEFINED_PRIVATE(iterator, stringIteratorNextIndexSymbol)) {
|
if (!HAS_DEFINED_PRIVATE(iterator, stringIteratorNextIndexSymbol)) {
|
||||||
throw MakeTypeError(kIncompatibleMethodReceiver,
|
throw MakeTypeError(kIncompatibleMethodReceiver,
|
||||||
|
@ -1112,8 +1112,8 @@ function StringFromCodePoint(_) { // length = 1
|
|||||||
function StringRaw(callSite) {
|
function StringRaw(callSite) {
|
||||||
// TODO(caitp): Use rest parameters when implemented
|
// TODO(caitp): Use rest parameters when implemented
|
||||||
var numberOfSubstitutions = %_ArgumentsLength();
|
var numberOfSubstitutions = %_ArgumentsLength();
|
||||||
var cooked = $toObject(callSite);
|
var cooked = TO_OBJECT(callSite);
|
||||||
var raw = $toObject(cooked.raw);
|
var raw = TO_OBJECT(cooked.raw);
|
||||||
var literalSegments = $toLength(raw.length);
|
var literalSegments = $toLength(raw.length);
|
||||||
if (literalSegments <= 0) return "";
|
if (literalSegments <= 0) return "";
|
||||||
|
|
||||||
|
@ -78,7 +78,7 @@ function SymbolKeyFor(symbol) {
|
|||||||
|
|
||||||
// ES6 19.1.2.8
|
// ES6 19.1.2.8
|
||||||
function ObjectGetOwnPropertySymbols(obj) {
|
function ObjectGetOwnPropertySymbols(obj) {
|
||||||
obj = $toObject(obj);
|
obj = TO_OBJECT(obj);
|
||||||
|
|
||||||
// TODO(arv): Proxies use a shared trap for String and Symbol keys.
|
// TODO(arv): Proxies use a shared trap for String and Symbol keys.
|
||||||
|
|
||||||
|
@ -141,7 +141,7 @@ utils.InstallFunctions(global, DONT_ENUM, [
|
|||||||
function ObjectToString() {
|
function ObjectToString() {
|
||||||
if (IS_UNDEFINED(this) && !IS_UNDETECTABLE(this)) return "[object Undefined]";
|
if (IS_UNDEFINED(this) && !IS_UNDETECTABLE(this)) return "[object Undefined]";
|
||||||
if (IS_NULL(this)) return "[object Null]";
|
if (IS_NULL(this)) return "[object Null]";
|
||||||
var O = TO_OBJECT_INLINE(this);
|
var O = TO_OBJECT(this);
|
||||||
var builtinTag = %_ClassOf(O);
|
var builtinTag = %_ClassOf(O);
|
||||||
var tag;
|
var tag;
|
||||||
|
|
||||||
@ -168,14 +168,14 @@ function ObjectToLocaleString() {
|
|||||||
|
|
||||||
// ECMA-262 - 15.2.4.4
|
// ECMA-262 - 15.2.4.4
|
||||||
function ObjectValueOf() {
|
function ObjectValueOf() {
|
||||||
return TO_OBJECT_INLINE(this);
|
return TO_OBJECT(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// ECMA-262 - 15.2.4.5
|
// ECMA-262 - 15.2.4.5
|
||||||
function ObjectHasOwnProperty(value) {
|
function ObjectHasOwnProperty(value) {
|
||||||
var name = $toName(value);
|
var name = $toName(value);
|
||||||
var object = TO_OBJECT_INLINE(this);
|
var object = TO_OBJECT(this);
|
||||||
|
|
||||||
if (%_IsJSProxy(object)) {
|
if (%_IsJSProxy(object)) {
|
||||||
// TODO(rossberg): adjust once there is a story for symbols vs proxies.
|
// TODO(rossberg): adjust once there is a story for symbols vs proxies.
|
||||||
@ -206,7 +206,7 @@ function ObjectPropertyIsEnumerable(V) {
|
|||||||
var desc = GetOwnPropertyJS(this, P);
|
var desc = GetOwnPropertyJS(this, P);
|
||||||
return IS_UNDEFINED(desc) ? false : desc.isEnumerable();
|
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.setGet(fun);
|
||||||
desc.setEnumerable(true);
|
desc.setEnumerable(true);
|
||||||
desc.setConfigurable(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)) {
|
if (receiver == null && !IS_UNDETECTABLE(receiver)) {
|
||||||
receiver = %GlobalProxy(ObjectLookupGetter);
|
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.setSet(fun);
|
||||||
desc.setEnumerable(true);
|
desc.setEnumerable(true);
|
||||||
desc.setConfigurable(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)) {
|
if (receiver == null && !IS_UNDETECTABLE(receiver)) {
|
||||||
receiver = %GlobalProxy(ObjectLookupSetter);
|
receiver = %GlobalProxy(ObjectLookupSetter);
|
||||||
}
|
}
|
||||||
return %LookupAccessor(TO_OBJECT_INLINE(receiver), $toName(name), SETTER);
|
return %LookupAccessor(TO_OBJECT(receiver), $toName(name), SETTER);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function ObjectKeys(obj) {
|
function ObjectKeys(obj) {
|
||||||
obj = TO_OBJECT_INLINE(obj);
|
obj = TO_OBJECT(obj);
|
||||||
if (%_IsJSProxy(obj)) {
|
if (%_IsJSProxy(obj)) {
|
||||||
var handler = %GetHandler(obj);
|
var handler = %GetHandler(obj);
|
||||||
var names = CallTrap0(handler, "keys", ProxyDerivedKeysTrap);
|
var names = CallTrap0(handler, "keys", ProxyDerivedKeysTrap);
|
||||||
@ -579,7 +579,7 @@ function GetOwnPropertyJS(obj, v) {
|
|||||||
// GetOwnProperty returns an array indexed by the constants
|
// GetOwnProperty returns an array indexed by the constants
|
||||||
// defined in macros.py.
|
// defined in macros.py.
|
||||||
// If p is not a property on obj undefined is returned.
|
// 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);
|
return ConvertDescriptorArrayToDescriptor(props);
|
||||||
}
|
}
|
||||||
@ -868,7 +868,7 @@ function DefineOwnPropertyFromAPI(obj, p, value, desc) {
|
|||||||
|
|
||||||
// ES6 section 19.1.2.9
|
// ES6 section 19.1.2.9
|
||||||
function ObjectGetPrototypeOf(obj) {
|
function ObjectGetPrototypeOf(obj) {
|
||||||
return %_GetPrototype(TO_OBJECT_INLINE(obj));
|
return %_GetPrototype(TO_OBJECT(obj));
|
||||||
}
|
}
|
||||||
|
|
||||||
// ES6 section 19.1.2.19.
|
// ES6 section 19.1.2.19.
|
||||||
@ -889,7 +889,7 @@ function ObjectSetPrototypeOf(obj, proto) {
|
|||||||
|
|
||||||
// ES6 section 19.1.2.6
|
// ES6 section 19.1.2.6
|
||||||
function ObjectGetOwnPropertyDescriptor(obj, p) {
|
function ObjectGetOwnPropertyDescriptor(obj, p) {
|
||||||
var desc = GetOwnPropertyJS(TO_OBJECT_INLINE(obj), p);
|
var desc = GetOwnPropertyJS(TO_OBJECT(obj), p);
|
||||||
return FromPropertyDescriptor(desc);
|
return FromPropertyDescriptor(desc);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1001,7 +1001,7 @@ function OwnPropertyKeys(obj) {
|
|||||||
|
|
||||||
// ES5 section 15.2.3.4.
|
// ES5 section 15.2.3.4.
|
||||||
function ObjectGetOwnPropertyNames(obj) {
|
function ObjectGetOwnPropertyNames(obj) {
|
||||||
obj = TO_OBJECT_INLINE(obj);
|
obj = TO_OBJECT(obj);
|
||||||
// Special handling for proxies.
|
// Special handling for proxies.
|
||||||
if (%_IsJSProxy(obj)) {
|
if (%_IsJSProxy(obj)) {
|
||||||
var handler = %GetHandler(obj);
|
var handler = %GetHandler(obj);
|
||||||
@ -1093,7 +1093,7 @@ function ObjectDefineProperties(obj, properties) {
|
|||||||
if (!IS_SPEC_OBJECT(obj)) {
|
if (!IS_SPEC_OBJECT(obj)) {
|
||||||
throw MakeTypeError(kCalledOnNonObject, "Object.defineProperties");
|
throw MakeTypeError(kCalledOnNonObject, "Object.defineProperties");
|
||||||
}
|
}
|
||||||
var props = TO_OBJECT_INLINE(properties);
|
var props = TO_OBJECT(properties);
|
||||||
var names = GetOwnEnumerablePropertyNames(props);
|
var names = GetOwnEnumerablePropertyNames(props);
|
||||||
var descriptors = new InternalArray();
|
var descriptors = new InternalArray();
|
||||||
for (var i = 0; i < names.length; i++) {
|
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
|
// ECMA-262, Edition 6, section B.2.2.1.1
|
||||||
function ObjectGetProto() {
|
function ObjectGetProto() {
|
||||||
return %_GetPrototype(TO_OBJECT_INLINE(this));
|
return %_GetPrototype(TO_OBJECT(this));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1280,10 +1280,10 @@ function ObjectSetProto(proto) {
|
|||||||
function ObjectConstructor(x) {
|
function ObjectConstructor(x) {
|
||||||
if (%_IsConstructCall()) {
|
if (%_IsConstructCall()) {
|
||||||
if (x == null) return this;
|
if (x == null) return this;
|
||||||
return TO_OBJECT_INLINE(x);
|
return TO_OBJECT(x);
|
||||||
} else {
|
} else {
|
||||||
if (x == null) return { };
|
if (x == null) return { };
|
||||||
return TO_OBJECT_INLINE(x);
|
return TO_OBJECT(x);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1053,8 +1053,9 @@ void Builtins::Generate_FunctionCall(MacroAssembler* masm) {
|
|||||||
__ Integer32ToSmi(rax, rax);
|
__ Integer32ToSmi(rax, rax);
|
||||||
__ Push(rax);
|
__ Push(rax);
|
||||||
|
|
||||||
__ Push(rbx);
|
__ movp(rax, rbx);
|
||||||
__ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
|
ToObjectStub stub(masm->isolate());
|
||||||
|
__ CallStub(&stub);
|
||||||
__ movp(rbx, rax);
|
__ movp(rbx, rax);
|
||||||
__ Set(rdx, 0); // indicate regular JS_FUNCTION
|
__ 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.
|
// Convert the receiver to an object.
|
||||||
__ bind(&call_to_object);
|
__ bind(&call_to_object);
|
||||||
__ Push(rbx);
|
__ movp(rax, rbx);
|
||||||
__ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
|
ToObjectStub stub(masm->isolate());
|
||||||
|
__ CallStub(&stub);
|
||||||
__ movp(rbx, rax);
|
__ movp(rbx, rax);
|
||||||
__ jmp(&push_receiver, Label::kNear);
|
__ jmp(&push_receiver, Label::kNear);
|
||||||
|
|
||||||
|
@ -1964,8 +1964,8 @@ static void EmitWrapCase(MacroAssembler* masm,
|
|||||||
// Wrap the receiver and patch it back onto the stack.
|
// Wrap the receiver and patch it back onto the stack.
|
||||||
{ FrameScope frame_scope(masm, StackFrame::INTERNAL);
|
{ FrameScope frame_scope(masm, StackFrame::INTERNAL);
|
||||||
__ Push(rdi);
|
__ Push(rdi);
|
||||||
__ Push(rax);
|
ToObjectStub stub(masm->isolate());
|
||||||
__ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
|
__ CallStub(&stub);
|
||||||
__ Pop(rdi);
|
__ Pop(rdi);
|
||||||
}
|
}
|
||||||
__ movp(args->GetReceiverOperand(), rax);
|
__ movp(args->GetReceiverOperand(), rax);
|
||||||
|
@ -103,6 +103,10 @@ void ToNumberDescriptor::InitializePlatformSpecific(
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// static
|
||||||
|
const Register ToObjectDescriptor::ReceiverRegister() { return rax; }
|
||||||
|
|
||||||
|
|
||||||
void NumberToStringDescriptor::InitializePlatformSpecific(
|
void NumberToStringDescriptor::InitializePlatformSpecific(
|
||||||
CallInterfaceDescriptorData* data) {
|
CallInterfaceDescriptorData* data) {
|
||||||
Register registers[] = {rax};
|
Register registers[] = {rax};
|
||||||
|
@ -994,8 +994,9 @@ void Builtins::Generate_FunctionCall(MacroAssembler* masm) {
|
|||||||
__ SmiTag(eax);
|
__ SmiTag(eax);
|
||||||
__ push(eax);
|
__ push(eax);
|
||||||
|
|
||||||
__ push(ebx);
|
__ mov(eax, ebx);
|
||||||
__ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
|
ToObjectStub stub(masm->isolate());
|
||||||
|
__ CallStub(&stub);
|
||||||
__ mov(ebx, eax);
|
__ mov(ebx, eax);
|
||||||
__ Move(edx, Immediate(0)); // restore
|
__ Move(edx, Immediate(0)); // restore
|
||||||
|
|
||||||
@ -1215,8 +1216,9 @@ static void Generate_ApplyHelper(MacroAssembler* masm, bool targetIsArgument) {
|
|||||||
__ j(above_equal, &push_receiver);
|
__ j(above_equal, &push_receiver);
|
||||||
|
|
||||||
__ bind(&call_to_object);
|
__ bind(&call_to_object);
|
||||||
__ push(ebx);
|
__ mov(eax, ebx);
|
||||||
__ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
|
ToObjectStub stub(masm->isolate());
|
||||||
|
__ CallStub(&stub);
|
||||||
__ mov(ebx, eax);
|
__ mov(ebx, eax);
|
||||||
__ jmp(&push_receiver);
|
__ jmp(&push_receiver);
|
||||||
|
|
||||||
|
@ -1800,8 +1800,8 @@ static void EmitWrapCase(MacroAssembler* masm, int argc, Label* cont) {
|
|||||||
// Wrap the receiver and patch it back onto the stack.
|
// Wrap the receiver and patch it back onto the stack.
|
||||||
{ FrameScope frame_scope(masm, StackFrame::INTERNAL);
|
{ FrameScope frame_scope(masm, StackFrame::INTERNAL);
|
||||||
__ push(edi);
|
__ push(edi);
|
||||||
__ push(eax);
|
ToObjectStub stub(masm->isolate());
|
||||||
__ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
|
__ CallStub(&stub);
|
||||||
__ pop(edi);
|
__ pop(edi);
|
||||||
}
|
}
|
||||||
__ mov(Operand(esp, (argc + 1) * kPointerSize), eax);
|
__ mov(Operand(esp, (argc + 1) * kPointerSize), eax);
|
||||||
|
@ -103,6 +103,10 @@ void ToNumberDescriptor::InitializePlatformSpecific(
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// static
|
||||||
|
const Register ToObjectDescriptor::ReceiverRegister() { return eax; }
|
||||||
|
|
||||||
|
|
||||||
void NumberToStringDescriptor::InitializePlatformSpecific(
|
void NumberToStringDescriptor::InitializePlatformSpecific(
|
||||||
CallInterfaceDescriptorData* data) {
|
CallInterfaceDescriptorData* data) {
|
||||||
Register registers[] = {eax};
|
Register registers[] = {eax};
|
||||||
|
Loading…
Reference in New Issue
Block a user