static const int kJSObjectHeaderSize = 3 * kApiPointerSize;
static const int kFixedArrayHeaderSize = 2 * kApiPointerSize;
static const int kContextHeaderSize = 2 * kApiPointerSize;
- static const int kContextEmbedderDataIndex = 82;
+ static const int kContextEmbedderDataIndex = 81;
static const int kFullStringRepresentationMask = 0x07;
static const int kStringEncodingMask = 0x4;
static const int kExternalTwoByteRepresentationTag = 0x02;
__ SmiTag(r0);
__ push(r0);
- __ push(r2);
- __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
+ __ mov(r0, r2);
+ ToObjectStub stub(masm->isolate());
+ __ CallStub(&stub);
__ mov(r2, r0);
__ pop(r0);
// Convert the receiver to a regular object.
// r0: receiver
__ bind(&call_to_object);
- __ push(r0);
- __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
+ ToObjectStub stub(masm->isolate());
+ __ CallStub(&stub);
__ b(&push_receiver);
__ bind(&use_global_proxy);
static void EmitWrapCase(MacroAssembler* masm, int argc, Label* cont) {
// Wrap the receiver and patch it back onto the stack.
{ FrameAndConstantPoolScope frame_scope(masm, StackFrame::INTERNAL);
- __ Push(r1, r3);
- __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
+ __ push(r1);
+ __ mov(r0, r3);
+ ToObjectStub stub(masm->isolate());
+ __ CallStub(&stub);
__ pop(r1);
}
__ str(r0, MemOperand(sp, argc * kPointerSize));
}
+// static
+const Register ToObjectDescriptor::ReceiverRegister() { return r0; }
+
+
void NumberToStringDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
Register registers[] = {r0};
FrameScope scope(masm, StackFrame::INTERNAL);
__ SmiTag(argc);
- __ Push(argc, receiver);
- __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
+ __ Push(argc);
+ __ Mov(x0, receiver);
+ ToObjectStub stub(masm->isolate());
+ __ CallStub(&stub);
__ Mov(receiver, x0);
__ Pop(argc);
// Call a builtin to convert the receiver to a regular object.
__ Bind(&convert_receiver_to_object);
- __ Push(receiver);
- __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
+ __ Mov(x0, receiver);
+ ToObjectStub stub(masm->isolate());
+ __ CallStub(&stub);
__ Mov(receiver, x0);
__ B(&push_receiver);
static void EmitWrapCase(MacroAssembler* masm, int argc, Label* cont) {
// Wrap the receiver and patch it back onto the stack.
{ FrameScope frame_scope(masm, StackFrame::INTERNAL);
- __ Push(x1, x3);
- __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
+ __ Push(x1);
+ __ Mov(x0, x3);
+ ToObjectStub stub(masm->isolate());
+ __ CallStub(&stub);
__ Pop(x1);
}
__ Poke(x0, argc * kPointerSize);
}
+// static
+const Register ToObjectDescriptor::ReceiverRegister() { return x0; }
+
+
void NumberToStringDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
// x0: value
// 15.4.5.1 CreateArrayIterator Abstract Operation
function CreateArrayIterator(array, kind) {
- var object = $toObject(array);
+ var object = TO_OBJECT(array);
var iterator = new ArrayIterator;
SET_PRIVATE(iterator, arrayIteratorObjectSymbol, object);
SET_PRIVATE(iterator, arrayIteratorNextIndexSymbol, 0);
// 15.4.5.2.2 ArrayIterator.prototype.next( )
function ArrayIteratorNext() {
- var iterator = $toObject(this);
+ var iterator = TO_OBJECT(this);
if (!HAS_DEFINED_PRIVATE(iterator, arrayIteratorNextIndexSymbol)) {
throw MakeTypeError(kIncompatibleMethodReceiver,
// According to ES5, section 15.4.4.3, the toLocaleString conversion
// must throw a TypeError if ToObject(e).toLocaleString isn't
// callable.
- var e_obj = $toObject(e);
+ var e_obj = TO_OBJECT(e);
return $toString(e_obj.toLocaleString());
}
}
}
array = this;
} else {
- array = $toObject(this);
+ array = TO_OBJECT(this);
func = array.join;
}
if (!IS_SPEC_FUNCTION(func)) {
function ArrayToLocaleString() {
- var array = $toObject(this);
+ var array = TO_OBJECT(this);
var arrayLen = array.length;
return InnerArrayToLocaleString(array, arrayLen);
}
function ArrayJoin(separator) {
CHECK_OBJECT_COERCIBLE(this, "Array.prototype.join");
- var array = TO_OBJECT_INLINE(this);
+ var array = TO_OBJECT(this);
var length = TO_UINT32(array.length);
return InnerArrayJoin(separator, array, length);
function ArrayPop() {
CHECK_OBJECT_COERCIBLE(this, "Array.prototype.pop");
- var array = TO_OBJECT_INLINE(this);
+ var array = TO_OBJECT(this);
var n = TO_UINT32(array.length);
if (n == 0) {
array.length = n;
if (%IsObserved(this))
return ObservedArrayPush.apply(this, arguments);
- var array = TO_OBJECT_INLINE(this);
+ var array = TO_OBJECT(this);
var n = TO_UINT32(array.length);
var m = %_ArgumentsLength();
function ArrayConcatJS(arg1) { // length == 1
CHECK_OBJECT_COERCIBLE(this, "Array.prototype.concat");
- var array = $toObject(this);
+ var array = TO_OBJECT(this);
var arg_count = %_ArgumentsLength();
var arrays = new InternalArray(1 + arg_count);
arrays[0] = array;
function ArrayReverse() {
CHECK_OBJECT_COERCIBLE(this, "Array.prototype.reverse");
- var array = TO_OBJECT_INLINE(this);
+ var array = TO_OBJECT(this);
var len = TO_UINT32(array.length);
var isArray = IS_ARRAY(array);
function ArrayShift() {
CHECK_OBJECT_COERCIBLE(this, "Array.prototype.shift");
- var array = TO_OBJECT_INLINE(this);
+ var array = TO_OBJECT(this);
var len = TO_UINT32(array.length);
if (len === 0) {
if (%IsObserved(this))
return ObservedArrayUnshift.apply(this, arguments);
- var array = TO_OBJECT_INLINE(this);
+ var array = TO_OBJECT(this);
var len = TO_UINT32(array.length);
var num_arguments = %_ArgumentsLength();
function ArraySlice(start, end) {
CHECK_OBJECT_COERCIBLE(this, "Array.prototype.slice");
- var array = TO_OBJECT_INLINE(this);
+ var array = TO_OBJECT(this);
var len = TO_UINT32(array.length);
var start_i = TO_INTEGER(start);
var end_i = len;
return ObservedArraySplice.apply(this, arguments);
var num_arguments = %_ArgumentsLength();
- var array = TO_OBJECT_INLINE(this);
+ var array = TO_OBJECT(this);
var len = TO_UINT32(array.length);
var start_i = ComputeSpliceStartIndex(TO_INTEGER(start), len);
var del_count = ComputeSpliceDeleteCount(delete_count, num_arguments, len,
function ArraySort(comparefn) {
CHECK_OBJECT_COERCIBLE(this, "Array.prototype.sort");
- var array = $toObject(this);
+ var array = TO_OBJECT(this);
var length = TO_UINT32(array.length);
return %_CallFunction(array, length, comparefn, InnerArraySort);
}
var element = array[i];
// Prepare break slots for debugger step in.
if (stepping) %DebugPrepareStepInIfStepping(f);
- var new_receiver = needs_wrapper ? $toObject(receiver) : receiver;
+ var new_receiver = needs_wrapper ? TO_OBJECT(receiver) : receiver;
if (%_CallFunction(new_receiver, element, i, array, f)) {
accumulator[accumulator_length++] = element;
}
// Pull out the length so that modifications to the length in the
// loop will not affect the looping and side effects are visible.
- var array = $toObject(this);
+ var array = TO_OBJECT(this);
var length = $toUint32(array.length);
var accumulator = InnerArrayFilter(f, receiver, array, length);
var result = new GlobalArray();
var element = array[i];
// Prepare break slots for debugger step in.
if (stepping) %DebugPrepareStepInIfStepping(f);
- var new_receiver = needs_wrapper ? $toObject(receiver) : receiver;
+ var new_receiver = needs_wrapper ? TO_OBJECT(receiver) : receiver;
%_CallFunction(new_receiver, element, i, array, f);
}
}
// Pull out the length so that modifications to the length in the
// loop will not affect the looping and side effects are visible.
- var array = $toObject(this);
+ var array = TO_OBJECT(this);
var length = TO_UINT32(array.length);
InnerArrayForEach(f, receiver, array, length);
}
var element = array[i];
// Prepare break slots for debugger step in.
if (stepping) %DebugPrepareStepInIfStepping(f);
- var new_receiver = needs_wrapper ? $toObject(receiver) : receiver;
+ var new_receiver = needs_wrapper ? TO_OBJECT(receiver) : receiver;
if (%_CallFunction(new_receiver, element, i, array, f)) return true;
}
}
// Pull out the length so that modifications to the length in the
// loop will not affect the looping and side effects are visible.
- var array = $toObject(this);
+ var array = TO_OBJECT(this);
var length = TO_UINT32(array.length);
return InnerArraySome(f, receiver, array, length);
}
var element = array[i];
// Prepare break slots for debugger step in.
if (stepping) %DebugPrepareStepInIfStepping(f);
- var new_receiver = needs_wrapper ? $toObject(receiver) : receiver;
+ var new_receiver = needs_wrapper ? TO_OBJECT(receiver) : receiver;
if (!%_CallFunction(new_receiver, element, i, array, f)) return false;
}
}
// Pull out the length so that modifications to the length in the
// loop will not affect the looping and side effects are visible.
- var array = $toObject(this);
+ var array = TO_OBJECT(this);
var length = TO_UINT32(array.length);
return InnerArrayEvery(f, receiver, array, length);
}
var element = array[i];
// Prepare break slots for debugger step in.
if (stepping) %DebugPrepareStepInIfStepping(f);
- var new_receiver = needs_wrapper ? $toObject(receiver) : receiver;
+ var new_receiver = needs_wrapper ? TO_OBJECT(receiver) : receiver;
accumulator[i] = %_CallFunction(new_receiver, element, i, array, f);
}
}
// Pull out the length so that modifications to the length in the
// loop will not affect the looping and side effects are visible.
- var array = $toObject(this);
+ var array = TO_OBJECT(this);
var length = TO_UINT32(array.length);
var accumulator = InnerArrayMap(f, receiver, array, length);
var result = new GlobalArray();
// Pull out the length so that modifications to the length in the
// loop will not affect the looping and side effects are visible.
- var array = $toObject(this);
+ var array = TO_OBJECT(this);
var length = $toUint32(array.length);
return InnerArrayReduce(callback, current, array, length,
%_ArgumentsLength());
// Pull out the length so that side effects are visible before the
// callback function is checked.
- var array = $toObject(this);
+ var array = TO_OBJECT(this);
var length = $toUint32(array.length);
return InnerArrayReduceRight(callback, current, array, length,
%_ArgumentsLength());
INSTALL_NATIVE(JSFunction, "$toNumber", to_number_fun);
INSTALL_NATIVE(JSFunction, "$toString", to_string_fun);
INSTALL_NATIVE(JSFunction, "$toDetailString", to_detail_string_fun);
- INSTALL_NATIVE(JSFunction, "$toObject", to_object_fun);
INSTALL_NATIVE(JSFunction, "$toInteger", to_integer_fun);
INSTALL_NATIVE(JSFunction, "$toUint32", to_uint32_fun);
INSTALL_NATIVE(JSFunction, "$toInt32", to_int32_fun);
V(CALL_NON_FUNCTION_AS_CONSTRUCTOR, 0) \
V(CALL_FUNCTION_PROXY, 1) \
V(CALL_FUNCTION_PROXY_AS_CONSTRUCTOR, 1) \
- V(TO_OBJECT, 0) \
V(TO_NUMBER, 0) \
V(TO_STRING, 0) \
V(TO_NAME, 0) \
// static
+Callable CodeFactory::ToObject(Isolate* isolate) {
+ ToObjectStub stub(isolate);
+ return Callable(stub.GetCode(), stub.GetCallInterfaceDescriptor());
+}
+
+
+// static
Callable CodeFactory::StringAdd(Isolate* isolate, StringAddFlags flags,
PretenureFlag pretenure_flag) {
StringAddStub stub(isolate, flags, pretenure_flag);
ToBooleanStub::Types types = ToBooleanStub::Types());
static Callable ToNumber(Isolate* isolate);
+ static Callable ToObject(Isolate* isolate);
static Callable StringAdd(Isolate* isolate, StringAddFlags flags,
PretenureFlag pretenure_flag);
}
+template <>
+HValue* CodeStubGraphBuilder<ToObjectStub>::BuildCodeStub() {
+ HValue* receiver = GetParameter(ToObjectDescriptor::kReceiverIndex);
+ return BuildToObject(receiver);
+}
+
+
+Handle<Code> ToObjectStub::GenerateCode() { return DoGenerateCode(this); }
+
+
void CodeStubGraphBuilderBase::BuildCheckAndInstallOptimizedCode(
HValue* js_function,
HValue* native_context,
}
+void ToObjectStub::InitializeDescriptor(CodeStubDescriptor* descriptor) {
+ descriptor->Initialize(Runtime::FunctionForId(Runtime::kToObject)->entry);
+}
+
+
CallInterfaceDescriptor StoreTransitionStub::GetCallInterfaceDescriptor()
const {
return StoreTransitionDescriptor(isolate());
V(StubFailureTrampoline) \
V(SubString) \
V(ToNumber) \
+ V(ToObject) \
V(VectorStoreICTrampoline) \
V(VectorKeyedStoreICTrampoline) \
V(VectorStoreIC) \
};
+class ToObjectStub final : public HydrogenCodeStub {
+ public:
+ explicit ToObjectStub(Isolate* isolate) : HydrogenCodeStub(isolate) {}
+
+ DEFINE_CALL_INTERFACE_DESCRIPTOR(ToObject);
+ DEFINE_HYDROGEN_CODE_STUB(ToObject, HydrogenCodeStub);
+};
+
+
class StringCompareStub : public PlatformCodeStub {
public:
explicit StringCompareStub(Isolate* isolate) : PlatformCodeStub(isolate) {}
while (%SetIteratorNext(iterator, value_array)) {
if (stepping) %DebugPrepareStepInIfStepping(f);
key = value_array[0];
- var new_receiver = needs_wrapper ? $toObject(receiver) : receiver;
+ var new_receiver = needs_wrapper ? TO_OBJECT(receiver) : receiver;
%_CallFunction(new_receiver, key, key, this, f);
}
}
var value_array = [UNDEFINED, UNDEFINED];
while (%MapIteratorNext(iterator, value_array)) {
if (stepping) %DebugPrepareStepInIfStepping(f);
- var new_receiver = needs_wrapper ? $toObject(receiver) : receiver;
+ var new_receiver = needs_wrapper ? TO_OBJECT(receiver) : receiver;
%_CallFunction(new_receiver, value_array[1], value_array[0], this, f);
}
}
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);
}
return ReduceGetTypeFeedbackVector(node);
case Runtime::kInlineGetCallerJSFunction:
return ReduceGetCallerJSFunction(node);
+ case Runtime::kInlineToObject:
+ return ReduceToObject(node);
case Runtime::kInlineThrowNotDateError:
return ReduceThrowNotDateError(node);
case Runtime::kInlineCallFunction:
}
+Reduction JSIntrinsicLowering::ReduceToObject(Node* node) {
+ node->set_op(javascript()->ToObject());
+ return Changed(node);
+}
+
+
Reduction JSIntrinsicLowering::ReduceCallFunction(Node* node) {
CallRuntimeParameters params = OpParameter<CallRuntimeParameters>(node->op());
size_t arity = params.arity();
Reduction ReduceGetTypeFeedbackVector(Node* node);
Reduction ReduceGetCallerJSFunction(Node* node);
Reduction ReduceThrowNotDateError(Node* node);
+ Reduction ReduceToObject(Node* node);
Reduction ReduceCallFunction(Node* node);
Reduction Change(Node* node, const Operator* op);
case Runtime::kInlineGetCallerJSFunction:
case Runtime::kInlineGetPrototype:
case Runtime::kInlineRegExpExec:
+ case Runtime::kInlineToObject:
return 1;
case Runtime::kInlineDeoptimizeNow:
case Runtime::kInlineThrowNotDateError:
return Bounds(Type::None(), Type::Range(0, 32, zone()));
case Runtime::kInlineStringGetLength:
return Bounds(Type::None(), Type::Range(0, String::kMaxLength, zone()));
+ case Runtime::kInlineToObject:
+ return Bounds(Type::None(), Type::Receiver());
default:
break;
}
V(TO_NUMBER_FUN_INDEX, JSFunction, to_number_fun) \
V(TO_STRING_FUN_INDEX, JSFunction, to_string_fun) \
V(TO_DETAIL_STRING_FUN_INDEX, JSFunction, to_detail_string_fun) \
- V(TO_OBJECT_FUN_INDEX, JSFunction, to_object_fun) \
V(TO_INTEGER_FUN_INDEX, JSFunction, to_integer_fun) \
V(TO_UINT32_FUN_INDEX, JSFunction, to_uint32_fun) \
V(TO_INT32_FUN_INDEX, JSFunction, to_int32_fun) \
TO_NUMBER_FUN_INDEX,
TO_STRING_FUN_INDEX,
TO_DETAIL_STRING_FUN_INDEX,
- TO_OBJECT_FUN_INDEX,
TO_INTEGER_FUN_INDEX,
TO_UINT32_FUN_INDEX,
TO_INT32_FUN_INDEX,
function DateToJSON(key) {
- var o = $toObject(this);
+ var o = TO_OBJECT(this);
var tv = $defaultNumber(o);
if (IS_NUMBER(tv) && !NUMBER_IS_FINITE(tv)) {
return null;
V(kValueMismatch, "value mismatch") \
V(kWrongInstanceType, "wrong instance type") \
V(kWrongMap, "wrong map") \
- V(kUndefinedOrNullInForIn, "null or undefined in for-in")
+ V(kUndefinedOrNullInForIn, "null or undefined in for-in") \
+ V(kUndefinedOrNullInToObject, "null or undefined in ToObject")
class Deoptimizer : public Malloced {
}
-MaybeHandle<Object> Execution::ToObject(
- Isolate* isolate, Handle<Object> obj) {
- if (obj->IsSpecObject()) return obj;
- // TODO(verwaest): Use Object::ToObject but throw an exception on failure.
- RETURN_NATIVE_CALL(to_object, { obj });
-}
-
-
MaybeHandle<Object> Execution::ToInteger(
Isolate* isolate, Handle<Object> obj) {
RETURN_NATIVE_CALL(to_integer, { obj });
#undef RETURN_NATIVE_CALL
+MaybeHandle<Object> Execution::ToObject(Isolate* isolate, Handle<Object> obj) {
+ Handle<JSReceiver> receiver;
+ if (JSReceiver::ToObject(isolate, obj).ToHandle(&receiver)) {
+ return receiver;
+ }
+ THROW_NEW_ERROR(
+ isolate, NewTypeError(MessageTemplate::kUndefinedOrNullToObject), Object);
+}
+
+
MaybeHandle<JSRegExp> Execution::NewJSRegExp(Handle<String> pattern,
Handle<String> flags) {
Isolate* isolate = pattern->GetIsolate();
__ CompareObjectType(r0, r1, r1, FIRST_SPEC_OBJECT_TYPE);
__ b(ge, &done_convert);
__ bind(&convert);
- __ push(r0);
- __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
+ ToObjectStub stub(isolate());
+ __ CallStub(&stub);
__ bind(&done_convert);
PrepareForBailoutForId(stmt->ToObjectId(), TOS_REG);
__ push(r0);
}
+void FullCodeGenerator::EmitToObject(CallRuntime* expr) {
+ ZoneList<Expression*>* args = expr->arguments();
+ DCHECK_EQ(1, args->length());
+
+ // Load the argument into r0 and convert it.
+ VisitForAccumulatorValue(args->at(0));
+
+ ToObjectStub stub(isolate());
+ __ CallStub(&stub);
+ context()->Plug(r0);
+}
+
+
void FullCodeGenerator::EmitStringCharFromCode(CallRuntime* expr) {
ZoneList<Expression*>* args = expr->arguments();
DCHECK(args->length() == 1);
__ JumpIfSmi(x0, &convert);
__ JumpIfObjectType(x0, x10, x11, FIRST_SPEC_OBJECT_TYPE, &done_convert, ge);
__ Bind(&convert);
- __ Push(x0);
- __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
+ ToObjectStub stub(isolate());
+ __ CallStub(&stub);
__ Bind(&done_convert);
PrepareForBailoutForId(stmt->ToObjectId(), TOS_REG);
__ Push(x0);
}
+void FullCodeGenerator::EmitToObject(CallRuntime* expr) {
+ ZoneList<Expression*>* args = expr->arguments();
+ DCHECK_EQ(1, args->length());
+
+ // Load the argument into x0 and convert it.
+ VisitForAccumulatorValue(args->at(0));
+
+ ToObjectStub stub(isolate());
+ __ CallStub(&stub);
+ context()->Plug(x0);
+}
+
+
void FullCodeGenerator::EmitStringCharFromCode(CallRuntime* expr) {
ZoneList<Expression*>* args = expr->arguments();
DCHECK(args->length() == 1);
F(RegExpConstructResult) \
F(GetFromCache) \
F(NumberToString) \
+ F(ToObject) \
F(DebugIsActive)
#define GENERATOR_DECLARATION(Name) void Emit##Name(CallRuntime* call);
__ CmpObjectType(eax, FIRST_SPEC_OBJECT_TYPE, ecx);
__ j(above_equal, &done_convert, Label::kNear);
__ bind(&convert);
- __ push(eax);
- __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
+ ToObjectStub stub(isolate());
+ __ CallStub(&stub);
__ bind(&done_convert);
PrepareForBailoutForId(stmt->ToObjectId(), TOS_REG);
__ push(eax);
}
+void FullCodeGenerator::EmitToObject(CallRuntime* expr) {
+ ZoneList<Expression*>* args = expr->arguments();
+ DCHECK_EQ(1, args->length());
+
+ // Load the argument into eax and convert it.
+ VisitForAccumulatorValue(args->at(0));
+
+ ToObjectStub stub(isolate());
+ __ CallStub(&stub);
+ context()->Plug(eax);
+}
+
+
void FullCodeGenerator::EmitStringCharFromCode(CallRuntime* expr) {
ZoneList<Expression*>* args = expr->arguments();
DCHECK(args->length() == 1);
__ GetObjectType(a0, a1, a1);
__ Branch(&done_convert, ge, a1, Operand(FIRST_SPEC_OBJECT_TYPE));
__ bind(&convert);
- __ push(a0);
- __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
+ ToObjectStub stub(isolate());
+ __ CallStub(&stub);
__ mov(a0, v0);
__ bind(&done_convert);
PrepareForBailoutForId(stmt->ToObjectId(), TOS_REG);
}
+void FullCodeGenerator::EmitToObject(CallRuntime* expr) {
+ ZoneList<Expression*>* args = expr->arguments();
+ DCHECK_EQ(1, args->length());
+
+ // Load the argument into a0 and convert it.
+ VisitForAccumulatorValue(args->at(0));
+ __ mov(a0, result_register());
+
+ ToObjectStub stub(isolate());
+ __ CallStub(&stub);
+ context()->Plug(v0);
+}
+
+
void FullCodeGenerator::EmitStringCharFromCode(CallRuntime* expr) {
ZoneList<Expression*>* args = expr->arguments();
DCHECK(args->length() == 1);
__ GetObjectType(a0, a1, a1);
__ Branch(&done_convert, ge, a1, Operand(FIRST_SPEC_OBJECT_TYPE));
__ bind(&convert);
- __ push(a0);
- __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
+ ToObjectStub stub(isolate());
+ __ CallStub(&stub);
__ mov(a0, v0);
__ bind(&done_convert);
PrepareForBailoutForId(stmt->ToObjectId(), TOS_REG);
}
+void FullCodeGenerator::EmitToObject(CallRuntime* expr) {
+ ZoneList<Expression*>* args = expr->arguments();
+ DCHECK_EQ(1, args->length());
+
+ // Load the argument into a0 and convert it.
+ VisitForAccumulatorValue(args->at(0));
+ __ mov(a0, result_register());
+
+ ToObjectStub stub(isolate());
+ __ CallStub(&stub);
+ context()->Plug(v0);
+}
+
+
void FullCodeGenerator::EmitStringCharFromCode(CallRuntime* expr) {
ZoneList<Expression*>* args = expr->arguments();
DCHECK(args->length() == 1);
__ CompareObjectType(r3, r4, r4, FIRST_SPEC_OBJECT_TYPE);
__ bge(&done_convert);
__ bind(&convert);
- __ push(r3);
- __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
+ ToObjectStub stub(isolate());
+ __ CallStub(&stub);
__ bind(&done_convert);
PrepareForBailoutForId(stmt->ToObjectId(), TOS_REG);
__ push(r3);
}
+void FullCodeGenerator::EmitToObject(CallRuntime* expr) {
+ ZoneList<Expression*>* args = expr->arguments();
+ DCHECK_EQ(1, args->length());
+ // Load the argument into r3 and convert it.
+ VisitForAccumulatorValue(args->at(0));
+
+ ToObjectStub stub(isolate());
+ __ CallStub(&stub);
+ context()->Plug(r3);
+}
+
+
void FullCodeGenerator::EmitStringCharFromCode(CallRuntime* expr) {
ZoneList<Expression*>* args = expr->arguments();
DCHECK(args->length() == 1);
// Convert the object to a JS object.
Label convert, done_convert;
- __ JumpIfSmi(rax, &convert);
+ __ JumpIfSmi(rax, &convert, Label::kNear);
__ CmpObjectType(rax, FIRST_SPEC_OBJECT_TYPE, rcx);
- __ j(above_equal, &done_convert);
+ __ j(above_equal, &done_convert, Label::kNear);
__ bind(&convert);
- __ Push(rax);
- __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
+ ToObjectStub stub(isolate());
+ __ CallStub(&stub);
__ bind(&done_convert);
PrepareForBailoutForId(stmt->ToObjectId(), TOS_REG);
__ Push(rax);
}
+void FullCodeGenerator::EmitToObject(CallRuntime* expr) {
+ ZoneList<Expression*>* args = expr->arguments();
+ DCHECK_EQ(1, args->length());
+
+ // Load the argument into rax and convert it.
+ VisitForAccumulatorValue(args->at(0));
+
+ ToObjectStub stub(isolate());
+ __ CallStub(&stub);
+ context()->Plug(rax);
+}
+
+
void FullCodeGenerator::EmitStringCharFromCode(CallRuntime* expr) {
ZoneList<Expression*>* args = expr->arguments();
DCHECK(args->length() == 1);
__ CmpObjectType(eax, FIRST_SPEC_OBJECT_TYPE, ecx);
__ j(above_equal, &done_convert, Label::kNear);
__ bind(&convert);
- __ push(eax);
- __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
+ ToObjectStub stub(isolate());
+ __ CallStub(&stub);
__ bind(&done_convert);
PrepareForBailoutForId(stmt->ToObjectId(), TOS_REG);
__ push(eax);
}
+void FullCodeGenerator::EmitToObject(CallRuntime* expr) {
+ ZoneList<Expression*>* args = expr->arguments();
+ DCHECK_EQ(1, args->length());
+
+ // Load the argument into eax and convert it.
+ VisitForAccumulatorValue(args->at(0));
+
+ ToObjectStub stub(isolate());
+ __ CallStub(&stub);
+ context()->Plug(eax);
+}
+
+
void FullCodeGenerator::EmitStringCharFromCode(CallRuntime* expr) {
ZoneList<Expression*>* args = expr->arguments();
DCHECK(args->length() == 1);
// https://github.com/tc39/Array.prototype.includes
// 6e3b78c927aeda20b9d40e81303f9d44596cd904
function ArrayIncludes(searchElement, fromIndex) {
- var array = $toObject(this);
+ var array = TO_OBJECT(this);
var len = $toLength(array.length);
if (len === 0) {
function ArrayCopyWithin(target, start, end) {
CHECK_OBJECT_COERCIBLE(this, "Array.prototype.copyWithin");
- var array = TO_OBJECT_INLINE(this);
+ var array = TO_OBJECT(this);
var length = $toLength(array.length);
return InnerArrayCopyWithin(target, start, end, array, length);
for (var i = 0; i < length; i++) {
var element = array[i];
- var newThisArg = needs_wrapper ? $toObject(thisArg) : thisArg;
+ var newThisArg = needs_wrapper ? TO_OBJECT(thisArg) : thisArg;
if (%_CallFunction(newThisArg, element, i, array, predicate)) {
return element;
}
function ArrayFind(predicate, thisArg) {
CHECK_OBJECT_COERCIBLE(this, "Array.prototype.find");
- var array = $toObject(this);
+ var array = TO_OBJECT(this);
var length = $toInteger(array.length);
return InnerArrayFind(predicate, thisArg, array, length);
for (var i = 0; i < length; i++) {
var element = array[i];
- var newThisArg = needs_wrapper ? $toObject(thisArg) : thisArg;
+ var newThisArg = needs_wrapper ? TO_OBJECT(thisArg) : thisArg;
if (%_CallFunction(newThisArg, element, i, array, predicate)) {
return i;
}
function ArrayFindIndex(predicate, thisArg) {
CHECK_OBJECT_COERCIBLE(this, "Array.prototype.findIndex");
- var array = $toObject(this);
+ var array = TO_OBJECT(this);
var length = $toInteger(array.length);
return InnerArrayFindIndex(predicate, thisArg, array, length);
function ArrayFill(value, start, end) {
CHECK_OBJECT_COERCIBLE(this, "Array.prototype.fill");
- var array = $toObject(this);
+ var array = TO_OBJECT(this);
var length = TO_UINT32(array.length);
return InnerArrayFill(value, start, end, array, length);
// ES6, draft 10-14-14, section 22.1.2.1
function ArrayFrom(arrayLike, mapfn, receiver) {
- var items = $toObject(arrayLike);
+ var items = TO_OBJECT(arrayLike);
var mapping = !IS_UNDEFINED(mapfn);
if (mapping) {
if (IS_NULL(receiver)) {
receiver = UNDEFINED;
} else if (!IS_UNDEFINED(receiver)) {
- receiver = TO_OBJECT_INLINE(receiver);
+ receiver = TO_OBJECT(receiver);
}
}
}
// ES6, draft 04-03-15, section 19.1.2.1
function ObjectAssign(target, sources) {
- var to = TO_OBJECT_INLINE(target);
+ var to = TO_OBJECT(target);
var argsLen = %_ArgumentsLength();
if (argsLen < 2) return to;
continue;
}
- var from = TO_OBJECT_INLINE(nextSource);
+ var from = TO_OBJECT(nextSource);
var keys = OwnPropertyKeys(from);
var len = keys.length;
}
+HValue* HGraphBuilder::BuildToObject(HValue* receiver) {
+ NoObservableSideEffectsScope scope(this);
+
+ // Create a joinable continuation.
+ HIfContinuation wrap(graph()->CreateBasicBlock(),
+ graph()->CreateBasicBlock());
+
+ // Determine the proper global constructor function required to wrap
+ // {receiver} into a JSValue, unless {receiver} is already a {JSReceiver}, in
+ // which case we just return it. Deopts to Runtime::kToObject if {receiver}
+ // is undefined or null.
+ IfBuilder receiver_is_smi(this);
+ receiver_is_smi.If<HIsSmiAndBranch>(receiver);
+ receiver_is_smi.Then();
+ {
+ // Load native context.
+ HValue* native_context = BuildGetNativeContext();
+
+ // Load global Number function.
+ HValue* constructor = Add<HLoadNamedField>(
+ native_context, nullptr,
+ HObjectAccess::ForContextSlot(Context::NUMBER_FUNCTION_INDEX));
+ Push(constructor);
+ }
+ receiver_is_smi.Else();
+ {
+ // Determine {receiver} map and instance type.
+ HValue* receiver_map =
+ Add<HLoadNamedField>(receiver, nullptr, HObjectAccess::ForMap());
+ HValue* receiver_instance_type = Add<HLoadNamedField>(
+ receiver_map, nullptr, HObjectAccess::ForMapInstanceType());
+
+ // First check whether {receiver} is already a spec object (fast case).
+ IfBuilder receiver_is_not_spec_object(this);
+ receiver_is_not_spec_object.If<HCompareNumericAndBranch>(
+ receiver_instance_type, Add<HConstant>(FIRST_SPEC_OBJECT_TYPE),
+ Token::LT);
+ receiver_is_not_spec_object.Then();
+ {
+ // Load native context.
+ HValue* native_context = BuildGetNativeContext();
+
+ IfBuilder receiver_is_heap_number(this);
+ receiver_is_heap_number.If<HCompareNumericAndBranch>(
+ receiver_instance_type, Add<HConstant>(HEAP_NUMBER_TYPE), Token::EQ);
+ receiver_is_heap_number.Then();
+ {
+ // Load global Number function.
+ HValue* constructor = Add<HLoadNamedField>(
+ native_context, nullptr,
+ HObjectAccess::ForContextSlot(Context::NUMBER_FUNCTION_INDEX));
+ Push(constructor);
+ }
+ receiver_is_heap_number.Else();
+ {
+ // Load boolean map (we cannot decide based on instance type, because
+ // it's ODDBALL_TYPE, which would also include null and undefined).
+ HValue* boolean_map = Add<HLoadRoot>(Heap::kBooleanMapRootIndex);
+
+ IfBuilder receiver_is_boolean(this);
+ receiver_is_boolean.If<HCompareObjectEqAndBranch>(receiver_map,
+ boolean_map);
+ receiver_is_boolean.Then();
+ {
+ // Load global Boolean function.
+ HValue* constructor = Add<HLoadNamedField>(
+ native_context, nullptr,
+ HObjectAccess::ForContextSlot(Context::BOOLEAN_FUNCTION_INDEX));
+ Push(constructor);
+ }
+ receiver_is_boolean.Else();
+ {
+ IfBuilder receiver_is_string(this);
+ receiver_is_string.If<HCompareNumericAndBranch>(
+ receiver_instance_type, Add<HConstant>(FIRST_NONSTRING_TYPE),
+ Token::LT);
+ receiver_is_string.Then();
+ {
+ // Load global String function.
+ HValue* constructor = Add<HLoadNamedField>(
+ native_context, nullptr,
+ HObjectAccess::ForContextSlot(Context::STRING_FUNCTION_INDEX));
+ Push(constructor);
+ }
+ receiver_is_string.Else();
+ {
+ IfBuilder receiver_is_symbol(this);
+ receiver_is_symbol.If<HCompareNumericAndBranch>(
+ receiver_instance_type, Add<HConstant>(SYMBOL_TYPE), Token::EQ);
+ receiver_is_symbol.Then();
+ {
+ // Load global Symbol function.
+ HValue* constructor = Add<HLoadNamedField>(
+ native_context, nullptr, HObjectAccess::ForContextSlot(
+ Context::SYMBOL_FUNCTION_INDEX));
+ Push(constructor);
+ }
+ receiver_is_symbol.Else();
+ {
+ IfBuilder receiver_is_float32x4(this);
+ receiver_is_float32x4.If<HCompareNumericAndBranch>(
+ receiver_instance_type, Add<HConstant>(FLOAT32X4_TYPE),
+ Token::EQ);
+ receiver_is_float32x4.Then();
+ {
+ // Load global Float32x4 function.
+ HValue* constructor = Add<HLoadNamedField>(
+ native_context, nullptr,
+ HObjectAccess::ForContextSlot(
+ Context::FLOAT32X4_FUNCTION_INDEX));
+ Push(constructor);
+ }
+ receiver_is_float32x4.ElseDeopt(
+ Deoptimizer::kUndefinedOrNullInToObject);
+ receiver_is_float32x4.JoinContinuation(&wrap);
+ }
+ receiver_is_symbol.JoinContinuation(&wrap);
+ }
+ receiver_is_string.JoinContinuation(&wrap);
+ }
+ receiver_is_boolean.JoinContinuation(&wrap);
+ }
+ receiver_is_heap_number.JoinContinuation(&wrap);
+ }
+ receiver_is_not_spec_object.JoinContinuation(&wrap);
+ }
+ receiver_is_smi.JoinContinuation(&wrap);
+
+ // Wrap the receiver if necessary.
+ IfBuilder if_wrap(this, &wrap);
+ if_wrap.Then();
+ {
+ // Determine the initial map for the global constructor.
+ HValue* constructor = Pop();
+ HValue* constructor_initial_map = Add<HLoadNamedField>(
+ constructor, nullptr, HObjectAccess::ForPrototypeOrInitialMap());
+ // Allocate and initialize a JSValue wrapper.
+ HValue* value =
+ BuildAllocate(Add<HConstant>(JSValue::kSize), HType::JSObject(),
+ JS_VALUE_TYPE, HAllocationMode());
+ Add<HStoreNamedField>(value, HObjectAccess::ForMap(),
+ constructor_initial_map);
+ HValue* empty_fixed_array = Add<HLoadRoot>(Heap::kEmptyFixedArrayRootIndex);
+ Add<HStoreNamedField>(value, HObjectAccess::ForPropertiesPointer(),
+ empty_fixed_array);
+ Add<HStoreNamedField>(value, HObjectAccess::ForElementsPointer(),
+ empty_fixed_array);
+ Add<HStoreNamedField>(value, HObjectAccess::ForObservableJSObjectOffset(
+ JSValue::kValueOffset),
+ receiver);
+ Push(value);
+ }
+ if_wrap.Else();
+ { Push(receiver); }
+ if_wrap.End();
+ return Pop();
+}
+
+
HAllocate* HGraphBuilder::BuildAllocate(
HValue* object_size,
HType type,
bool is_jsarray);
HValue* BuildNumberToString(HValue* object, Type* type);
+ HValue* BuildToObject(HValue* receiver);
void BuildJSObjectCheck(HValue* receiver,
int bit_field_mask);
if (IS_UNDEFINED(options)) {
options = {};
} else {
- options = $toObject(options);
+ options = TO_OBJECT(options);
}
var matcher = options.localeMatcher;
return freezeArray(seen);
}
- var o = $toObject(locales);
+ var o = TO_OBJECT(locales);
var len = TO_UINT32(o.length);
for (var k = 0; k < len; k++) {
return new Intl.Collator(locales, options);
}
- return initializeCollator($toObject(this), locales, options);
+ return initializeCollator(TO_OBJECT(this), locales, options);
},
DONT_ENUM
);
return new Intl.NumberFormat(locales, options);
}
- return initializeNumberFormat($toObject(this), locales, options);
+ return initializeNumberFormat(TO_OBJECT(this), locales, options);
},
DONT_ENUM
);
if (IS_UNDEFINED(options)) {
options = {};
} else {
- options = TO_OBJECT_INLINE(options);
+ options = TO_OBJECT(options);
}
var needsDefault = true;
return new Intl.DateTimeFormat(locales, options);
}
- return initializeDateTimeFormat($toObject(this), locales, options);
+ return initializeDateTimeFormat(TO_OBJECT(this), locales, options);
},
DONT_ENUM
);
return new Intl.v8BreakIterator(locales, options);
}
- return initializeBreakIterator($toObject(this), locales, options);
+ return initializeBreakIterator(TO_OBJECT(this), locales, options);
},
DONT_ENUM
);
__ SmiTag(eax);
__ push(eax);
- __ push(ebx);
- __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
+ __ mov(eax, ebx);
+ ToObjectStub stub(masm->isolate());
+ __ CallStub(&stub);
__ mov(ebx, eax);
__ Move(edx, Immediate(0)); // restore
__ j(above_equal, &push_receiver);
__ bind(&call_to_object);
- __ push(ebx);
- __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
+ __ mov(eax, ebx);
+ ToObjectStub stub(masm->isolate());
+ __ CallStub(&stub);
__ mov(ebx, eax);
__ jmp(&push_receiver);
// Wrap the receiver and patch it back onto the stack.
{ FrameScope frame_scope(masm, StackFrame::INTERNAL);
__ push(edi);
- __ push(eax);
- __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
+ ToObjectStub stub(masm->isolate());
+ __ CallStub(&stub);
__ pop(edi);
}
__ mov(Operand(esp, (argc + 1) * kPointerSize), eax);
}
+// static
+const Register ToObjectDescriptor::ReceiverRegister() { return eax; }
+
+
void NumberToStringDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
Register registers[] = {eax};
}
+void ToObjectDescriptor::InitializePlatformSpecific(
+ CallInterfaceDescriptorData* data) {
+ Register registers[] = {ReceiverRegister()};
+ data->InitializePlatformSpecific(arraysize(registers), registers);
+}
+
+
void MathPowTaggedDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
Register registers[] = {exponent()};
V(FastNewClosure) \
V(FastNewContext) \
V(ToNumber) \
+ V(ToObject) \
V(NumberToString) \
V(Typeof) \
V(FastCloneShallowArray) \
};
+class ToObjectDescriptor : public CallInterfaceDescriptor {
+ public:
+ enum ParameterIndices { kReceiverIndex };
+
+ DECLARE_DESCRIPTOR(ToObjectDescriptor, CallInterfaceDescriptor)
+
+ static const Register ReceiverRegister();
+};
+
+
class NumberToStringDescriptor : public CallInterfaceDescriptor {
public:
DECLARE_DESCRIPTOR(NumberToStringDescriptor, CallInterfaceDescriptor)
macro TO_UINT32(arg) = (arg >>> 0);
macro TO_STRING_INLINE(arg) = (IS_STRING(%IS_VAR(arg)) ? arg : $nonStringToString(arg));
macro TO_NUMBER_INLINE(arg) = (IS_NUMBER(%IS_VAR(arg)) ? arg : $nonNumberToNumber(arg));
-macro TO_OBJECT_INLINE(arg) = (IS_SPEC_OBJECT(%IS_VAR(arg)) ? arg : $toObject(arg));
+macro TO_OBJECT(arg) = (%_ToObject(arg));
macro JSON_NUMBER_TO_STRING(arg) = ((%_IsSmi(%IS_VAR(arg)) || arg - arg == 0) ? %_NumberToString(arg) : "null");
macro HAS_OWN_PROPERTY(arg, index) = (%_CallFunction(arg, index, ObjectHasOwnProperty));
macro SHOULD_CREATE_WRAPPER(functionName, receiver) = (!IS_SPEC_OBJECT(receiver) && %IsSloppyModeFunction(functionName));
function NoSideEffectsObjectToString() {
if (IS_UNDEFINED(this) && !IS_UNDETECTABLE(this)) return "[object Undefined]";
if (IS_NULL(this)) return "[object Null]";
- return "[object " + %_ClassOf(TO_OBJECT_INLINE(this)) + "]";
+ return "[object " + %_ClassOf(TO_OBJECT(this)) + "]";
}
{
FrameScope scope(masm, StackFrame::INTERNAL);
__ sll(a0, a0, kSmiTagSize); // Smi tagged.
- __ Push(a0, a2);
- __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
+ __ push(a0);
+ __ mov(a0, a2);
+ ToObjectStub stub(masm->isolate());
+ __ CallStub(&stub);
__ mov(a2, v0);
__ pop(a0);
// Convert the receiver to a regular object.
// a0: receiver
__ bind(&call_to_object);
- __ push(a0);
- __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
+ ToObjectStub stub(masm->isolate());
+ __ CallStub(&stub);
__ mov(a0, v0); // Put object in a0 to match other paths to push_receiver.
__ Branch(&push_receiver);
static void EmitWrapCase(MacroAssembler* masm, int argc, Label* cont) {
// Wrap the receiver and patch it back onto the stack.
{ FrameScope frame_scope(masm, StackFrame::INTERNAL);
- __ Push(a1, a3);
- __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
+ __ Push(a1);
+ __ mov(a0, a3);
+ ToObjectStub stub(masm->isolate());
+ __ CallStub(&stub);
__ pop(a1);
}
__ Branch(USE_DELAY_SLOT, cont);
}
+// static
+const Register ToObjectDescriptor::ReceiverRegister() { return a0; }
+
+
void NumberToStringDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
Register registers[] = {a0};
{
FrameScope scope(masm, StackFrame::INTERNAL);
__ SmiTag(a0);
- __ Push(a0, a2);
- __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
+ __ Push(a0);
+ __ mov(a0, a2);
+ ToObjectStub stub(masm->isolate());
+ __ CallStub(&stub);
__ mov(a2, v0);
__ pop(a0);
// Convert the receiver to a regular object.
// a0: receiver
__ bind(&call_to_object);
- __ push(a0);
- __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
+ ToObjectStub stub(masm->isolate());
+ __ CallStub(&stub);
__ mov(a0, v0); // Put object in a0 to match other paths to push_receiver.
__ Branch(&push_receiver);
static void EmitWrapCase(MacroAssembler* masm, int argc, Label* cont) {
// Wrap the receiver and patch it back onto the stack.
{ FrameScope frame_scope(masm, StackFrame::INTERNAL);
- __ Push(a1, a3);
- __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
+ __ Push(a1);
+ __ mov(a0, a3);
+ ToObjectStub stub(masm->isolate());
+ __ CallStub(&stub);
__ pop(a1);
}
__ Branch(USE_DELAY_SLOT, cont);
}
+// static
+const Register ToObjectDescriptor::ReceiverRegister() { return a0; }
+
+
void NumberToStringDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
Register registers[] = {a0};
// Enter an internal frame in order to preserve argument count.
FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL);
__ SmiTag(r3);
- __ Push(r3, r5);
- __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
+ __ Push(r3);
+ __ mr(r3, r5);
+ ToObjectStub stub(masm->isolate());
+ __ CallStub(&stub);
__ mr(r5, r3);
__ pop(r3);
// Convert the receiver to a regular object.
// r3: receiver
__ bind(&call_to_object);
- __ push(r3);
- __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
+ ToObjectStub stub(masm->isolate());
+ __ CallStub(&stub);
__ b(&push_receiver);
__ bind(&use_global_proxy);
// Wrap the receiver and patch it back onto the stack.
{
FrameAndConstantPoolScope frame_scope(masm, StackFrame::INTERNAL);
- __ Push(r4, r6);
- __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
+ __ push(r4);
+ __ mr(r3, r6);
+ ToObjectStub stub(masm->isolate());
+ __ CallStub(&stub);
__ pop(r4);
}
__ StoreP(r3, MemOperand(sp, argc * kPointerSize), r0);
}
+// static
+const Register ToObjectDescriptor::ReceiverRegister() { return r3; }
+
+
void NumberToStringDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
Register registers[] = {r3};
var REFLECT_APPLY_PREPARE;
var REFLECT_CONSTRUCT_PREPARE;
var STACK_OVERFLOW;
-var TO_OBJECT;
var TO_NUMBER;
var TO_STRING;
var TO_NAME;
var $toLength;
var $toName;
var $toNumber;
-var $toObject;
var $toPositiveInteger;
var $toPrimitive;
var $toString;
// ECMA-262, section 11.4.1, page 46.
DELETE = function DELETE(key, language_mode) {
- return %DeleteProperty(%$toObject(this), key, language_mode);
+ return %DeleteProperty(TO_OBJECT(this), key, language_mode);
}
}
-// Convert the receiver to an object - forward to ToObject.
-TO_OBJECT = function TO_OBJECT() {
- return %$toObject(this);
-}
-
-
// Convert the receiver to a number - forward to ToNumber.
TO_NUMBER = function TO_NUMBER() {
return %$toNumber(this);
}
-// ECMA-262, section 9.9, page 36.
-function ToObject(x) {
- if (IS_STRING(x)) return new GlobalString(x);
- if (IS_NUMBER(x)) return new GlobalNumber(x);
- if (IS_BOOLEAN(x)) return new GlobalBoolean(x);
- if (IS_SYMBOL(x)) return %NewSymbolWrapper(x);
- if (IS_FLOAT32X4(x)) return %NewFloat32x4Wrapper(x);
- if (IS_NULL_OR_UNDEFINED(x) && !IS_UNDETECTABLE(x)) {
- throw MakeTypeError(kUndefinedOrNullToObject);
- }
- return x;
-}
-
-
// ECMA-262, section 9.4, page 34.
function ToInteger(x) {
if (%_IsSmi(x)) return x;
$toLength = ToLength;
$toName = ToName;
$toNumber = ToNumber;
-$toObject = ToObject;
$toPositiveInteger = ToPositiveInteger;
$toPrimitive = ToPrimitive;
$toString = ToString;
setter, attrs));
return isolate->heap()->undefined_value();
}
+
+
+RUNTIME_FUNCTION(Runtime_ToObject) {
+ HandleScope scope(isolate);
+ DCHECK_EQ(1, args.length());
+ CONVERT_ARG_HANDLE_CHECKED(Object, object, 0);
+ Handle<JSReceiver> receiver;
+ if (JSReceiver::ToObject(isolate, object).ToHandle(&receiver)) {
+ return *receiver;
+ }
+ THROW_NEW_ERROR_RETURN_FAILURE(
+ isolate, NewTypeError(MessageTemplate::kUndefinedOrNullToObject));
+}
+
} // namespace internal
} // namespace v8
NumberTo##type##Component(*y), NumberTo##type##Component(*z)); \
}
-#define SIMD_CREATE_WRAPPER_FUNCTION(type) \
- RUNTIME_FUNCTION(Runtime_New##type##Wrapper) { \
- HandleScope scope(isolate); \
- DCHECK(args.length() == 1); \
- CONVERT_ARG_HANDLE_CHECKED(type, value, 0); \
- return *Object::ToObject(isolate, value).ToHandleChecked(); \
- }
-
#define SIMD_CHECK_FUNCTION(type) \
RUNTIME_FUNCTION(Runtime_##type##Check) { \
HandleScope scope(isolate); \
#define SIMD4_FUNCTIONS(type) \
SIMD4_CREATE_FUNCTION(type) \
- SIMD_CREATE_WRAPPER_FUNCTION(type) \
SIMD_CHECK_FUNCTION(type) \
SIMD4_EXTRACT_LANE_FUNCTION(type) \
SIMD4_EQUALS_FUNCTION(type) \
} // namespace
SIMD4_FUNCTIONS(Float32x4)
-}
-} // namespace v8::internal
+
+} // namespace internal
+} // namespace v8
}
-RUNTIME_FUNCTION(Runtime_NewSymbolWrapper) {
- HandleScope scope(isolate);
- DCHECK(args.length() == 1);
- CONVERT_ARG_HANDLE_CHECKED(Symbol, symbol, 0);
- return *Object::ToObject(isolate, symbol).ToHandleChecked();
-}
-
-
RUNTIME_FUNCTION(Runtime_SymbolDescription) {
SealHandleScope shs(isolate);
DCHECK(args.length() == 1);
F(IsStrong, 1, 1) \
F(ClassOf, 1, 1) \
F(DefineGetterPropertyUnchecked, 4, 1) \
- F(DefineSetterPropertyUnchecked, 4, 1)
+ F(DefineSetterPropertyUnchecked, 4, 1) \
+ F(ToObject, 1, 1)
#define FOR_EACH_INTRINSIC_OBSERVE(F) \
#define FOR_EACH_INTRINSIC_SIMD(F) \
F(CreateFloat32x4, 4, 1) \
- F(NewFloat32x4Wrapper, 1, 1) \
F(Float32x4Check, 1, 1) \
F(Float32x4ExtractLane, 2, 1) \
F(Float32x4Equals, 2, 1) \
F(CreateSymbol, 1, 1) \
F(CreatePrivateSymbol, 1, 1) \
F(CreateGlobalPrivateSymbol, 1, 1) \
- F(NewSymbolWrapper, 1, 1) \
F(SymbolDescription, 1, 1) \
F(SymbolRegistry, 0, 1) \
F(SymbolIsPrivate, 1, 1)
// 21.1.5.2.1 %StringIteratorPrototype%.next( )
function StringIteratorNext() {
- var iterator = $toObject(this);
+ var iterator = TO_OBJECT(this);
if (!HAS_DEFINED_PRIVATE(iterator, stringIteratorNextIndexSymbol)) {
throw MakeTypeError(kIncompatibleMethodReceiver,
function StringRaw(callSite) {
// TODO(caitp): Use rest parameters when implemented
var numberOfSubstitutions = %_ArgumentsLength();
- var cooked = $toObject(callSite);
- var raw = $toObject(cooked.raw);
+ var cooked = TO_OBJECT(callSite);
+ var raw = TO_OBJECT(cooked.raw);
var literalSegments = $toLength(raw.length);
if (literalSegments <= 0) return "";
// ES6 19.1.2.8
function ObjectGetOwnPropertySymbols(obj) {
- obj = $toObject(obj);
+ obj = TO_OBJECT(obj);
// TODO(arv): Proxies use a shared trap for String and Symbol keys.
function ObjectToString() {
if (IS_UNDEFINED(this) && !IS_UNDETECTABLE(this)) return "[object Undefined]";
if (IS_NULL(this)) return "[object Null]";
- var O = TO_OBJECT_INLINE(this);
+ var O = TO_OBJECT(this);
var builtinTag = %_ClassOf(O);
var tag;
// ECMA-262 - 15.2.4.4
function ObjectValueOf() {
- return TO_OBJECT_INLINE(this);
+ return TO_OBJECT(this);
}
// ECMA-262 - 15.2.4.5
function ObjectHasOwnProperty(value) {
var name = $toName(value);
- var object = TO_OBJECT_INLINE(this);
+ var object = TO_OBJECT(this);
if (%_IsJSProxy(object)) {
// TODO(rossberg): adjust once there is a story for symbols vs proxies.
var desc = GetOwnPropertyJS(this, P);
return IS_UNDEFINED(desc) ? false : desc.isEnumerable();
}
- return %IsPropertyEnumerable(TO_OBJECT_INLINE(this), P);
+ return %IsPropertyEnumerable(TO_OBJECT(this), P);
}
desc.setGet(fun);
desc.setEnumerable(true);
desc.setConfigurable(true);
- DefineOwnProperty(TO_OBJECT_INLINE(receiver), $toName(name), desc, false);
+ DefineOwnProperty(TO_OBJECT(receiver), $toName(name), desc, false);
}
if (receiver == null && !IS_UNDETECTABLE(receiver)) {
receiver = %GlobalProxy(ObjectLookupGetter);
}
- return %LookupAccessor(TO_OBJECT_INLINE(receiver), $toName(name), GETTER);
+ return %LookupAccessor(TO_OBJECT(receiver), $toName(name), GETTER);
}
desc.setSet(fun);
desc.setEnumerable(true);
desc.setConfigurable(true);
- DefineOwnProperty(TO_OBJECT_INLINE(receiver), $toName(name), desc, false);
+ DefineOwnProperty(TO_OBJECT(receiver), $toName(name), desc, false);
}
if (receiver == null && !IS_UNDETECTABLE(receiver)) {
receiver = %GlobalProxy(ObjectLookupSetter);
}
- return %LookupAccessor(TO_OBJECT_INLINE(receiver), $toName(name), SETTER);
+ return %LookupAccessor(TO_OBJECT(receiver), $toName(name), SETTER);
}
function ObjectKeys(obj) {
- obj = TO_OBJECT_INLINE(obj);
+ obj = TO_OBJECT(obj);
if (%_IsJSProxy(obj)) {
var handler = %GetHandler(obj);
var names = CallTrap0(handler, "keys", ProxyDerivedKeysTrap);
// GetOwnProperty returns an array indexed by the constants
// defined in macros.py.
// If p is not a property on obj undefined is returned.
- var props = %GetOwnProperty(TO_OBJECT_INLINE(obj), p);
+ var props = %GetOwnProperty(TO_OBJECT(obj), p);
return ConvertDescriptorArrayToDescriptor(props);
}
// ES6 section 19.1.2.9
function ObjectGetPrototypeOf(obj) {
- return %_GetPrototype(TO_OBJECT_INLINE(obj));
+ return %_GetPrototype(TO_OBJECT(obj));
}
// ES6 section 19.1.2.19.
// ES6 section 19.1.2.6
function ObjectGetOwnPropertyDescriptor(obj, p) {
- var desc = GetOwnPropertyJS(TO_OBJECT_INLINE(obj), p);
+ var desc = GetOwnPropertyJS(TO_OBJECT(obj), p);
return FromPropertyDescriptor(desc);
}
// ES5 section 15.2.3.4.
function ObjectGetOwnPropertyNames(obj) {
- obj = TO_OBJECT_INLINE(obj);
+ obj = TO_OBJECT(obj);
// Special handling for proxies.
if (%_IsJSProxy(obj)) {
var handler = %GetHandler(obj);
if (!IS_SPEC_OBJECT(obj)) {
throw MakeTypeError(kCalledOnNonObject, "Object.defineProperties");
}
- var props = TO_OBJECT_INLINE(properties);
+ var props = TO_OBJECT(properties);
var names = GetOwnEnumerablePropertyNames(props);
var descriptors = new InternalArray();
for (var i = 0; i < names.length; i++) {
// ECMA-262, Edition 6, section B.2.2.1.1
function ObjectGetProto() {
- return %_GetPrototype(TO_OBJECT_INLINE(this));
+ return %_GetPrototype(TO_OBJECT(this));
}
function ObjectConstructor(x) {
if (%_IsConstructCall()) {
if (x == null) return this;
- return TO_OBJECT_INLINE(x);
+ return TO_OBJECT(x);
} else {
if (x == null) return { };
- return TO_OBJECT_INLINE(x);
+ return TO_OBJECT(x);
}
}
__ Integer32ToSmi(rax, rax);
__ Push(rax);
- __ Push(rbx);
- __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
+ __ movp(rax, rbx);
+ ToObjectStub stub(masm->isolate());
+ __ CallStub(&stub);
__ movp(rbx, rax);
__ Set(rdx, 0); // indicate regular JS_FUNCTION
// Convert the receiver to an object.
__ bind(&call_to_object);
- __ Push(rbx);
- __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
+ __ movp(rax, rbx);
+ ToObjectStub stub(masm->isolate());
+ __ CallStub(&stub);
__ movp(rbx, rax);
__ jmp(&push_receiver, Label::kNear);
// Wrap the receiver and patch it back onto the stack.
{ FrameScope frame_scope(masm, StackFrame::INTERNAL);
__ Push(rdi);
- __ Push(rax);
- __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
+ ToObjectStub stub(masm->isolate());
+ __ CallStub(&stub);
__ Pop(rdi);
}
__ movp(args->GetReceiverOperand(), rax);
}
+// static
+const Register ToObjectDescriptor::ReceiverRegister() { return rax; }
+
+
void NumberToStringDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
Register registers[] = {rax};
__ SmiTag(eax);
__ push(eax);
- __ push(ebx);
- __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
+ __ mov(eax, ebx);
+ ToObjectStub stub(masm->isolate());
+ __ CallStub(&stub);
__ mov(ebx, eax);
__ Move(edx, Immediate(0)); // restore
__ j(above_equal, &push_receiver);
__ bind(&call_to_object);
- __ push(ebx);
- __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
+ __ mov(eax, ebx);
+ ToObjectStub stub(masm->isolate());
+ __ CallStub(&stub);
__ mov(ebx, eax);
__ jmp(&push_receiver);
// Wrap the receiver and patch it back onto the stack.
{ FrameScope frame_scope(masm, StackFrame::INTERNAL);
__ push(edi);
- __ push(eax);
- __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
+ ToObjectStub stub(masm->isolate());
+ __ CallStub(&stub);
__ pop(edi);
}
__ mov(Operand(esp, (argc + 1) * kPointerSize), eax);
}
+// static
+const Register ToObjectDescriptor::ReceiverRegister() { return eax; }
+
+
void NumberToStringDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
Register registers[] = {eax};