From: bmeurer Date: Fri, 31 Jul 2015 12:25:28 +0000 (-0700) Subject: [stubs] Unify (and optimize) implementation of ToObject. X-Git-Tag: upstream/4.7.83~1087 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=4fc6f5472441523c1a46d0d273ba8b216f96250f;p=platform%2Fupstream%2Fv8.git [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} --- diff --git a/include/v8.h b/include/v8.h index 50f0f5fd2..0bcb311ba 100644 --- a/include/v8.h +++ b/include/v8.h @@ -6913,7 +6913,7 @@ class Internals { static const int kJSObjectHeaderSize = 3 * kApiPointerSize; static const int kFixedArrayHeaderSize = 2 * kApiPointerSize; static const int kContextHeaderSize = 2 * kApiPointerSize; - static const int kContextEmbedderDataIndex = 82; + static const int kContextEmbedderDataIndex = 81; static const int kFullStringRepresentationMask = 0x07; static const int kStringEncodingMask = 0x4; static const int kExternalTwoByteRepresentationTag = 0x02; diff --git a/src/arm/builtins-arm.cc b/src/arm/builtins-arm.cc index b33a1957e..113510c2b 100644 --- a/src/arm/builtins-arm.cc +++ b/src/arm/builtins-arm.cc @@ -1319,8 +1319,9 @@ void Builtins::Generate_FunctionCall(MacroAssembler* masm) { __ SmiTag(r0); __ push(r0); - __ push(r2); - __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION); + __ mov(r0, r2); + ToObjectStub stub(masm->isolate()); + __ CallStub(&stub); __ mov(r2, r0); __ pop(r0); @@ -1556,8 +1557,8 @@ static void Generate_ApplyHelper(MacroAssembler* masm, bool targetIsArgument) { // Convert the receiver to a regular object. // r0: receiver __ bind(&call_to_object); - __ push(r0); - __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION); + ToObjectStub stub(masm->isolate()); + __ CallStub(&stub); __ b(&push_receiver); __ bind(&use_global_proxy); diff --git a/src/arm/code-stubs-arm.cc b/src/arm/code-stubs-arm.cc index cc090d58d..80d01a176 100644 --- a/src/arm/code-stubs-arm.cc +++ b/src/arm/code-stubs-arm.cc @@ -2547,8 +2547,10 @@ static void EmitSlowCase(MacroAssembler* masm, static void EmitWrapCase(MacroAssembler* masm, int argc, Label* cont) { // Wrap the receiver and patch it back onto the stack. { FrameAndConstantPoolScope frame_scope(masm, StackFrame::INTERNAL); - __ Push(r1, r3); - __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION); + __ push(r1); + __ mov(r0, r3); + ToObjectStub stub(masm->isolate()); + __ CallStub(&stub); __ pop(r1); } __ str(r0, MemOperand(sp, argc * kPointerSize)); diff --git a/src/arm/interface-descriptors-arm.cc b/src/arm/interface-descriptors-arm.cc index e54dd5c05..ddaf9e521 100644 --- a/src/arm/interface-descriptors-arm.cc +++ b/src/arm/interface-descriptors-arm.cc @@ -95,6 +95,10 @@ void ToNumberDescriptor::InitializePlatformSpecific( } +// static +const Register ToObjectDescriptor::ReceiverRegister() { return r0; } + + void NumberToStringDescriptor::InitializePlatformSpecific( CallInterfaceDescriptorData* data) { Register registers[] = {r0}; diff --git a/src/arm64/builtins-arm64.cc b/src/arm64/builtins-arm64.cc index d93b5ad62..0cb956166 100644 --- a/src/arm64/builtins-arm64.cc +++ b/src/arm64/builtins-arm64.cc @@ -1355,8 +1355,10 @@ void Builtins::Generate_FunctionCall(MacroAssembler* masm) { FrameScope scope(masm, StackFrame::INTERNAL); __ SmiTag(argc); - __ Push(argc, receiver); - __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION); + __ Push(argc); + __ Mov(x0, receiver); + ToObjectStub stub(masm->isolate()); + __ CallStub(&stub); __ Mov(receiver, x0); __ Pop(argc); @@ -1582,8 +1584,9 @@ static void Generate_ApplyHelper(MacroAssembler* masm, bool targetIsArgument) { // Call a builtin to convert the receiver to a regular object. __ Bind(&convert_receiver_to_object); - __ Push(receiver); - __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION); + __ Mov(x0, receiver); + ToObjectStub stub(masm->isolate()); + __ CallStub(&stub); __ Mov(receiver, x0); __ B(&push_receiver); diff --git a/src/arm64/code-stubs-arm64.cc b/src/arm64/code-stubs-arm64.cc index d3493833e..b10364163 100644 --- a/src/arm64/code-stubs-arm64.cc +++ b/src/arm64/code-stubs-arm64.cc @@ -2921,8 +2921,10 @@ static void EmitSlowCase(MacroAssembler* masm, static void EmitWrapCase(MacroAssembler* masm, int argc, Label* cont) { // Wrap the receiver and patch it back onto the stack. { FrameScope frame_scope(masm, StackFrame::INTERNAL); - __ Push(x1, x3); - __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION); + __ Push(x1); + __ Mov(x0, x3); + ToObjectStub stub(masm->isolate()); + __ CallStub(&stub); __ Pop(x1); } __ Poke(x0, argc * kPointerSize); diff --git a/src/arm64/interface-descriptors-arm64.cc b/src/arm64/interface-descriptors-arm64.cc index d34478389..c8cbd3152 100644 --- a/src/arm64/interface-descriptors-arm64.cc +++ b/src/arm64/interface-descriptors-arm64.cc @@ -104,6 +104,10 @@ void ToNumberDescriptor::InitializePlatformSpecific( } +// static +const Register ToObjectDescriptor::ReceiverRegister() { return x0; } + + void NumberToStringDescriptor::InitializePlatformSpecific( CallInterfaceDescriptorData* data) { // x0: value diff --git a/src/array-iterator.js b/src/array-iterator.js index 965e672f0..24a9ba51a 100644 --- a/src/array-iterator.js +++ b/src/array-iterator.js @@ -45,7 +45,7 @@ function ArrayIterator() {} // 15.4.5.1 CreateArrayIterator Abstract Operation function CreateArrayIterator(array, kind) { - var object = $toObject(array); + var object = TO_OBJECT(array); var iterator = new ArrayIterator; SET_PRIVATE(iterator, arrayIteratorObjectSymbol, object); SET_PRIVATE(iterator, arrayIteratorNextIndexSymbol, 0); @@ -68,7 +68,7 @@ function ArrayIteratorIterator() { // 15.4.5.2.2 ArrayIterator.prototype.next( ) function ArrayIteratorNext() { - var iterator = $toObject(this); + var iterator = TO_OBJECT(this); if (!HAS_DEFINED_PRIVATE(iterator, arrayIteratorNextIndexSymbol)) { throw MakeTypeError(kIncompatibleMethodReceiver, diff --git a/src/array.js b/src/array.js index e0cc0695c..7d0fdcafb 100644 --- a/src/array.js +++ b/src/array.js @@ -227,7 +227,7 @@ function ConvertToLocaleString(e) { // According to ES5, section 15.4.4.3, the toLocaleString conversion // must throw a TypeError if ToObject(e).toLocaleString isn't // callable. - var e_obj = $toObject(e); + var e_obj = TO_OBJECT(e); return $toString(e_obj.toLocaleString()); } } @@ -388,7 +388,7 @@ function ArrayToString() { } array = this; } else { - array = $toObject(this); + array = TO_OBJECT(this); func = array.join; } if (!IS_SPEC_FUNCTION(func)) { @@ -406,7 +406,7 @@ function InnerArrayToLocaleString(array, length) { function ArrayToLocaleString() { - var array = $toObject(this); + var array = TO_OBJECT(this); var arrayLen = array.length; return InnerArrayToLocaleString(array, arrayLen); } @@ -437,7 +437,7 @@ function InnerArrayJoin(separator, array, length) { function ArrayJoin(separator) { CHECK_OBJECT_COERCIBLE(this, "Array.prototype.join"); - var array = TO_OBJECT_INLINE(this); + var array = TO_OBJECT(this); var length = TO_UINT32(array.length); return InnerArrayJoin(separator, array, length); @@ -466,7 +466,7 @@ function ObservedArrayPop(n) { function ArrayPop() { CHECK_OBJECT_COERCIBLE(this, "Array.prototype.pop"); - var array = TO_OBJECT_INLINE(this); + var array = TO_OBJECT(this); var n = TO_UINT32(array.length); if (n == 0) { array.length = n; @@ -512,7 +512,7 @@ function ArrayPush() { if (%IsObserved(this)) return ObservedArrayPush.apply(this, arguments); - var array = TO_OBJECT_INLINE(this); + var array = TO_OBJECT(this); var n = TO_UINT32(array.length); var m = %_ArgumentsLength(); @@ -532,7 +532,7 @@ function ArrayPush() { function ArrayConcatJS(arg1) { // length == 1 CHECK_OBJECT_COERCIBLE(this, "Array.prototype.concat"); - var array = $toObject(this); + var array = TO_OBJECT(this); var arg_count = %_ArgumentsLength(); var arrays = new InternalArray(1 + arg_count); arrays[0] = array; @@ -627,7 +627,7 @@ function GenericArrayReverse(array, len) { function ArrayReverse() { CHECK_OBJECT_COERCIBLE(this, "Array.prototype.reverse"); - var array = TO_OBJECT_INLINE(this); + var array = TO_OBJECT(this); var len = TO_UINT32(array.length); var isArray = IS_ARRAY(array); @@ -662,7 +662,7 @@ function ObservedArrayShift(len) { function ArrayShift() { CHECK_OBJECT_COERCIBLE(this, "Array.prototype.shift"); - var array = TO_OBJECT_INLINE(this); + var array = TO_OBJECT(this); var len = TO_UINT32(array.length); if (len === 0) { @@ -716,7 +716,7 @@ function ArrayUnshift(arg1) { // length == 1 if (%IsObserved(this)) return ObservedArrayUnshift.apply(this, arguments); - var array = TO_OBJECT_INLINE(this); + var array = TO_OBJECT(this); var len = TO_UINT32(array.length); var num_arguments = %_ArgumentsLength(); @@ -740,7 +740,7 @@ function ArrayUnshift(arg1) { // length == 1 function ArraySlice(start, end) { CHECK_OBJECT_COERCIBLE(this, "Array.prototype.slice"); - var array = TO_OBJECT_INLINE(this); + var array = TO_OBJECT(this); var len = TO_UINT32(array.length); var start_i = TO_INTEGER(start); var end_i = len; @@ -858,7 +858,7 @@ function ArraySplice(start, delete_count) { return ObservedArraySplice.apply(this, arguments); var num_arguments = %_ArgumentsLength(); - var array = TO_OBJECT_INLINE(this); + var array = TO_OBJECT(this); var len = TO_UINT32(array.length); var start_i = ComputeSpliceStartIndex(TO_INTEGER(start), len); var del_count = ComputeSpliceDeleteCount(delete_count, num_arguments, len, @@ -1190,7 +1190,7 @@ function InnerArraySort(length, comparefn) { function ArraySort(comparefn) { CHECK_OBJECT_COERCIBLE(this, "Array.prototype.sort"); - var array = $toObject(this); + var array = TO_OBJECT(this); var length = TO_UINT32(array.length); return %_CallFunction(array, length, comparefn, InnerArraySort); } @@ -1217,7 +1217,7 @@ function InnerArrayFilter(f, receiver, array, length) { var element = array[i]; // Prepare break slots for debugger step in. if (stepping) %DebugPrepareStepInIfStepping(f); - var new_receiver = needs_wrapper ? $toObject(receiver) : receiver; + var new_receiver = needs_wrapper ? TO_OBJECT(receiver) : receiver; if (%_CallFunction(new_receiver, element, i, array, f)) { accumulator[accumulator_length++] = element; } @@ -1231,7 +1231,7 @@ function ArrayFilter(f, receiver) { // Pull out the length so that modifications to the length in the // loop will not affect the looping and side effects are visible. - var array = $toObject(this); + var array = TO_OBJECT(this); var length = $toUint32(array.length); var accumulator = InnerArrayFilter(f, receiver, array, length); var result = new GlobalArray(); @@ -1255,7 +1255,7 @@ function InnerArrayForEach(f, receiver, array, length) { var element = array[i]; // Prepare break slots for debugger step in. if (stepping) %DebugPrepareStepInIfStepping(f); - var new_receiver = needs_wrapper ? $toObject(receiver) : receiver; + var new_receiver = needs_wrapper ? TO_OBJECT(receiver) : receiver; %_CallFunction(new_receiver, element, i, array, f); } } @@ -1266,7 +1266,7 @@ function ArrayForEach(f, receiver) { // Pull out the length so that modifications to the length in the // loop will not affect the looping and side effects are visible. - var array = $toObject(this); + var array = TO_OBJECT(this); var length = TO_UINT32(array.length); InnerArrayForEach(f, receiver, array, length); } @@ -1288,7 +1288,7 @@ function InnerArraySome(f, receiver, array, length) { var element = array[i]; // Prepare break slots for debugger step in. if (stepping) %DebugPrepareStepInIfStepping(f); - var new_receiver = needs_wrapper ? $toObject(receiver) : receiver; + var new_receiver = needs_wrapper ? TO_OBJECT(receiver) : receiver; if (%_CallFunction(new_receiver, element, i, array, f)) return true; } } @@ -1303,7 +1303,7 @@ function ArraySome(f, receiver) { // Pull out the length so that modifications to the length in the // loop will not affect the looping and side effects are visible. - var array = $toObject(this); + var array = TO_OBJECT(this); var length = TO_UINT32(array.length); return InnerArraySome(f, receiver, array, length); } @@ -1325,7 +1325,7 @@ function InnerArrayEvery(f, receiver, array, length) { var element = array[i]; // Prepare break slots for debugger step in. if (stepping) %DebugPrepareStepInIfStepping(f); - var new_receiver = needs_wrapper ? $toObject(receiver) : receiver; + var new_receiver = needs_wrapper ? TO_OBJECT(receiver) : receiver; if (!%_CallFunction(new_receiver, element, i, array, f)) return false; } } @@ -1337,7 +1337,7 @@ function ArrayEvery(f, receiver) { // Pull out the length so that modifications to the length in the // loop will not affect the looping and side effects are visible. - var array = $toObject(this); + var array = TO_OBJECT(this); var length = TO_UINT32(array.length); return InnerArrayEvery(f, receiver, array, length); } @@ -1360,7 +1360,7 @@ function InnerArrayMap(f, receiver, array, length) { var element = array[i]; // Prepare break slots for debugger step in. if (stepping) %DebugPrepareStepInIfStepping(f); - var new_receiver = needs_wrapper ? $toObject(receiver) : receiver; + var new_receiver = needs_wrapper ? TO_OBJECT(receiver) : receiver; accumulator[i] = %_CallFunction(new_receiver, element, i, array, f); } } @@ -1373,7 +1373,7 @@ function ArrayMap(f, receiver) { // Pull out the length so that modifications to the length in the // loop will not affect the looping and side effects are visible. - var array = $toObject(this); + var array = TO_OBJECT(this); var length = TO_UINT32(array.length); var accumulator = InnerArrayMap(f, receiver, array, length); var result = new GlobalArray(); @@ -1542,7 +1542,7 @@ function ArrayReduce(callback, current) { // Pull out the length so that modifications to the length in the // loop will not affect the looping and side effects are visible. - var array = $toObject(this); + var array = TO_OBJECT(this); var length = $toUint32(array.length); return InnerArrayReduce(callback, current, array, length, %_ArgumentsLength()); @@ -1585,7 +1585,7 @@ function ArrayReduceRight(callback, current) { // Pull out the length so that side effects are visible before the // callback function is checked. - var array = $toObject(this); + var array = TO_OBJECT(this); var length = $toUint32(array.length); return InnerArrayReduceRight(callback, current, array, length, %_ArgumentsLength()); diff --git a/src/bootstrapper.cc b/src/bootstrapper.cc index 5f2f9d3cd..838510000 100644 --- a/src/bootstrapper.cc +++ b/src/bootstrapper.cc @@ -1724,7 +1724,6 @@ void Genesis::InstallNativeFunctions() { INSTALL_NATIVE(JSFunction, "$toNumber", to_number_fun); INSTALL_NATIVE(JSFunction, "$toString", to_string_fun); INSTALL_NATIVE(JSFunction, "$toDetailString", to_detail_string_fun); - INSTALL_NATIVE(JSFunction, "$toObject", to_object_fun); INSTALL_NATIVE(JSFunction, "$toInteger", to_integer_fun); INSTALL_NATIVE(JSFunction, "$toUint32", to_uint32_fun); INSTALL_NATIVE(JSFunction, "$toInt32", to_int32_fun); diff --git a/src/builtins.h b/src/builtins.h index d7cd720fe..212ad89e4 100644 --- a/src/builtins.h +++ b/src/builtins.h @@ -182,7 +182,6 @@ enum BuiltinExtraArguments { V(CALL_NON_FUNCTION_AS_CONSTRUCTOR, 0) \ V(CALL_FUNCTION_PROXY, 1) \ V(CALL_FUNCTION_PROXY_AS_CONSTRUCTOR, 1) \ - V(TO_OBJECT, 0) \ V(TO_NUMBER, 0) \ V(TO_STRING, 0) \ V(TO_NAME, 0) \ diff --git a/src/code-factory.cc b/src/code-factory.cc index be3454994..acbf515c2 100644 --- a/src/code-factory.cc +++ b/src/code-factory.cc @@ -177,6 +177,13 @@ Callable CodeFactory::ToNumber(Isolate* isolate) { } +// static +Callable CodeFactory::ToObject(Isolate* isolate) { + ToObjectStub stub(isolate); + return Callable(stub.GetCode(), stub.GetCallInterfaceDescriptor()); +} + + // static Callable CodeFactory::StringAdd(Isolate* isolate, StringAddFlags flags, PretenureFlag pretenure_flag) { diff --git a/src/code-factory.h b/src/code-factory.h index f750ab649..1386f054b 100644 --- a/src/code-factory.h +++ b/src/code-factory.h @@ -73,6 +73,7 @@ class CodeFactory final { ToBooleanStub::Types types = ToBooleanStub::Types()); static Callable ToNumber(Isolate* isolate); + static Callable ToObject(Isolate* isolate); static Callable StringAdd(Isolate* isolate, StringAddFlags flags, PretenureFlag pretenure_flag); diff --git a/src/code-stubs-hydrogen.cc b/src/code-stubs-hydrogen.cc index fb46633f0..4afd592ab 100644 --- a/src/code-stubs-hydrogen.cc +++ b/src/code-stubs-hydrogen.cc @@ -1657,6 +1657,16 @@ Handle ElementsTransitionAndStoreStub::GenerateCode() { } +template <> +HValue* CodeStubGraphBuilder::BuildCodeStub() { + HValue* receiver = GetParameter(ToObjectDescriptor::kReceiverIndex); + return BuildToObject(receiver); +} + + +Handle ToObjectStub::GenerateCode() { return DoGenerateCode(this); } + + void CodeStubGraphBuilderBase::BuildCheckAndInstallOptimizedCode( HValue* js_function, HValue* native_context, diff --git a/src/code-stubs.cc b/src/code-stubs.cc index ee57db741..cc77389de 100644 --- a/src/code-stubs.cc +++ b/src/code-stubs.cc @@ -672,6 +672,11 @@ void ElementsTransitionAndStoreStub::InitializeDescriptor( } +void ToObjectStub::InitializeDescriptor(CodeStubDescriptor* descriptor) { + descriptor->Initialize(Runtime::FunctionForId(Runtime::kToObject)->entry); +} + + CallInterfaceDescriptor StoreTransitionStub::GetCallInterfaceDescriptor() const { return StoreTransitionDescriptor(isolate()); diff --git a/src/code-stubs.h b/src/code-stubs.h index 372b788fe..f1759ee36 100644 --- a/src/code-stubs.h +++ b/src/code-stubs.h @@ -54,6 +54,7 @@ namespace internal { V(StubFailureTrampoline) \ V(SubString) \ V(ToNumber) \ + V(ToObject) \ V(VectorStoreICTrampoline) \ V(VectorKeyedStoreICTrampoline) \ V(VectorStoreIC) \ @@ -3050,6 +3051,15 @@ class ToNumberStub final : public PlatformCodeStub { }; +class ToObjectStub final : public HydrogenCodeStub { + public: + explicit ToObjectStub(Isolate* isolate) : HydrogenCodeStub(isolate) {} + + DEFINE_CALL_INTERFACE_DESCRIPTOR(ToObject); + DEFINE_HYDROGEN_CODE_STUB(ToObject, HydrogenCodeStub); +}; + + class StringCompareStub : public PlatformCodeStub { public: explicit StringCompareStub(Isolate* isolate) : PlatformCodeStub(isolate) {} diff --git a/src/collection.js b/src/collection.js index ceab1642c..f0bc42392 100644 --- a/src/collection.js +++ b/src/collection.js @@ -268,7 +268,7 @@ function SetForEach(f, receiver) { while (%SetIteratorNext(iterator, value_array)) { if (stepping) %DebugPrepareStepInIfStepping(f); key = value_array[0]; - var new_receiver = needs_wrapper ? $toObject(receiver) : receiver; + var new_receiver = needs_wrapper ? TO_OBJECT(receiver) : receiver; %_CallFunction(new_receiver, key, key, this, f); } } @@ -457,7 +457,7 @@ function MapForEach(f, receiver) { var value_array = [UNDEFINED, UNDEFINED]; while (%MapIteratorNext(iterator, value_array)) { if (stepping) %DebugPrepareStepInIfStepping(f); - var new_receiver = needs_wrapper ? $toObject(receiver) : receiver; + var new_receiver = needs_wrapper ? TO_OBJECT(receiver) : receiver; %_CallFunction(new_receiver, value_array[1], value_array[0], this, f); } } diff --git a/src/compiler/js-generic-lowering.cc b/src/compiler/js-generic-lowering.cc index a9861fc8f..0219aac67 100644 --- a/src/compiler/js-generic-lowering.cc +++ b/src/compiler/js-generic-lowering.cc @@ -307,7 +307,9 @@ void JSGenericLowering::LowerJSToName(Node* node) { void JSGenericLowering::LowerJSToObject(Node* node) { - ReplaceWithBuiltinCall(node, Builtins::TO_OBJECT, 1); + CallDescriptor::Flags flags = AdjustFrameStatesForCall(node); + Callable callable = CodeFactory::ToObject(isolate()); + ReplaceWithStubCall(node, callable, flags); } diff --git a/src/compiler/js-intrinsic-lowering.cc b/src/compiler/js-intrinsic-lowering.cc index 06ade91dd..e82ac205c 100644 --- a/src/compiler/js-intrinsic-lowering.cc +++ b/src/compiler/js-intrinsic-lowering.cc @@ -94,6 +94,8 @@ Reduction JSIntrinsicLowering::Reduce(Node* node) { return ReduceGetTypeFeedbackVector(node); case Runtime::kInlineGetCallerJSFunction: return ReduceGetCallerJSFunction(node); + case Runtime::kInlineToObject: + return ReduceToObject(node); case Runtime::kInlineThrowNotDateError: return ReduceThrowNotDateError(node); case Runtime::kInlineCallFunction: @@ -528,6 +530,12 @@ Reduction JSIntrinsicLowering::ReduceThrowNotDateError(Node* node) { } +Reduction JSIntrinsicLowering::ReduceToObject(Node* node) { + node->set_op(javascript()->ToObject()); + return Changed(node); +} + + Reduction JSIntrinsicLowering::ReduceCallFunction(Node* node) { CallRuntimeParameters params = OpParameter(node->op()); size_t arity = params.arity(); diff --git a/src/compiler/js-intrinsic-lowering.h b/src/compiler/js-intrinsic-lowering.h index 816defbf5..c14882c73 100644 --- a/src/compiler/js-intrinsic-lowering.h +++ b/src/compiler/js-intrinsic-lowering.h @@ -58,6 +58,7 @@ class JSIntrinsicLowering final : public AdvancedReducer { Reduction ReduceGetTypeFeedbackVector(Node* node); Reduction ReduceGetCallerJSFunction(Node* node); Reduction ReduceThrowNotDateError(Node* node); + Reduction ReduceToObject(Node* node); Reduction ReduceCallFunction(Node* node); Reduction Change(Node* node, const Operator* op); diff --git a/src/compiler/linkage.cc b/src/compiler/linkage.cc index c604909b8..51b29e3ad 100644 --- a/src/compiler/linkage.cc +++ b/src/compiler/linkage.cc @@ -219,6 +219,7 @@ int Linkage::FrameStateInputCount(Runtime::FunctionId function) { case Runtime::kInlineGetCallerJSFunction: case Runtime::kInlineGetPrototype: case Runtime::kInlineRegExpExec: + case Runtime::kInlineToObject: return 1; case Runtime::kInlineDeoptimizeNow: case Runtime::kInlineThrowNotDateError: diff --git a/src/compiler/typer.cc b/src/compiler/typer.cc index 85b73c825..aabcf4b5a 100644 --- a/src/compiler/typer.cc +++ b/src/compiler/typer.cc @@ -1559,6 +1559,8 @@ Bounds Typer::Visitor::TypeJSCallRuntime(Node* node) { return Bounds(Type::None(), Type::Range(0, 32, zone())); case Runtime::kInlineStringGetLength: return Bounds(Type::None(), Type::Range(0, String::kMaxLength, zone())); + case Runtime::kInlineToObject: + return Bounds(Type::None(), Type::Receiver()); default: break; } diff --git a/src/contexts.h b/src/contexts.h index 37fc31565..8e8f0b379 100644 --- a/src/contexts.h +++ b/src/contexts.h @@ -97,7 +97,6 @@ enum BindingFlags { V(TO_NUMBER_FUN_INDEX, JSFunction, to_number_fun) \ V(TO_STRING_FUN_INDEX, JSFunction, to_string_fun) \ V(TO_DETAIL_STRING_FUN_INDEX, JSFunction, to_detail_string_fun) \ - V(TO_OBJECT_FUN_INDEX, JSFunction, to_object_fun) \ V(TO_INTEGER_FUN_INDEX, JSFunction, to_integer_fun) \ V(TO_UINT32_FUN_INDEX, JSFunction, to_uint32_fun) \ V(TO_INT32_FUN_INDEX, JSFunction, to_int32_fun) \ @@ -363,7 +362,6 @@ class Context: public FixedArray { TO_NUMBER_FUN_INDEX, TO_STRING_FUN_INDEX, TO_DETAIL_STRING_FUN_INDEX, - TO_OBJECT_FUN_INDEX, TO_INTEGER_FUN_INDEX, TO_UINT32_FUN_INDEX, TO_INT32_FUN_INDEX, diff --git a/src/date.js b/src/date.js index 118c8a69c..56a72f0db 100644 --- a/src/date.js +++ b/src/date.js @@ -775,7 +775,7 @@ function DateToISOString() { function DateToJSON(key) { - var o = $toObject(this); + var o = TO_OBJECT(this); var tv = $defaultNumber(o); if (IS_NUMBER(tv) && !NUMBER_IS_FINITE(tv)) { return null; diff --git a/src/deoptimizer.h b/src/deoptimizer.h index ab76d41b6..854f08b8c 100644 --- a/src/deoptimizer.h +++ b/src/deoptimizer.h @@ -385,7 +385,8 @@ class OptimizedFunctionVisitor BASE_EMBEDDED { V(kValueMismatch, "value mismatch") \ V(kWrongInstanceType, "wrong instance type") \ V(kWrongMap, "wrong map") \ - V(kUndefinedOrNullInForIn, "null or undefined in for-in") + V(kUndefinedOrNullInForIn, "null or undefined in for-in") \ + V(kUndefinedOrNullInToObject, "null or undefined in ToObject") class Deoptimizer : public Malloced { diff --git a/src/execution.cc b/src/execution.cc index cdfa78744..687c0f99f 100644 --- a/src/execution.cc +++ b/src/execution.cc @@ -548,14 +548,6 @@ MaybeHandle Execution::ToDetailString( } -MaybeHandle Execution::ToObject( - Isolate* isolate, Handle obj) { - if (obj->IsSpecObject()) return obj; - // TODO(verwaest): Use Object::ToObject but throw an exception on failure. - RETURN_NATIVE_CALL(to_object, { obj }); -} - - MaybeHandle Execution::ToInteger( Isolate* isolate, Handle obj) { RETURN_NATIVE_CALL(to_integer, { obj }); @@ -589,6 +581,16 @@ MaybeHandle Execution::NewDate(Isolate* isolate, double time) { #undef RETURN_NATIVE_CALL +MaybeHandle Execution::ToObject(Isolate* isolate, Handle obj) { + Handle receiver; + if (JSReceiver::ToObject(isolate, obj).ToHandle(&receiver)) { + return receiver; + } + THROW_NEW_ERROR( + isolate, NewTypeError(MessageTemplate::kUndefinedOrNullToObject), Object); +} + + MaybeHandle Execution::NewJSRegExp(Handle pattern, Handle flags) { Isolate* isolate = pattern->GetIsolate(); diff --git a/src/full-codegen/arm/full-codegen-arm.cc b/src/full-codegen/arm/full-codegen-arm.cc index a4d017e01..c07438a2d 100644 --- a/src/full-codegen/arm/full-codegen-arm.cc +++ b/src/full-codegen/arm/full-codegen-arm.cc @@ -1083,8 +1083,8 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) { __ CompareObjectType(r0, r1, r1, FIRST_SPEC_OBJECT_TYPE); __ b(ge, &done_convert); __ bind(&convert); - __ push(r0); - __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION); + ToObjectStub stub(isolate()); + __ CallStub(&stub); __ bind(&done_convert); PrepareForBailoutForId(stmt->ToObjectId(), TOS_REG); __ push(r0); @@ -4018,6 +4018,19 @@ void FullCodeGenerator::EmitNumberToString(CallRuntime* expr) { } +void FullCodeGenerator::EmitToObject(CallRuntime* expr) { + ZoneList* 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* args = expr->arguments(); DCHECK(args->length() == 1); diff --git a/src/full-codegen/arm64/full-codegen-arm64.cc b/src/full-codegen/arm64/full-codegen-arm64.cc index 205af1e09..99cf86366 100644 --- a/src/full-codegen/arm64/full-codegen-arm64.cc +++ b/src/full-codegen/arm64/full-codegen-arm64.cc @@ -1085,8 +1085,8 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) { __ JumpIfSmi(x0, &convert); __ JumpIfObjectType(x0, x10, x11, FIRST_SPEC_OBJECT_TYPE, &done_convert, ge); __ Bind(&convert); - __ Push(x0); - __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION); + ToObjectStub stub(isolate()); + __ CallStub(&stub); __ Bind(&done_convert); PrepareForBailoutForId(stmt->ToObjectId(), TOS_REG); __ Push(x0); @@ -3726,6 +3726,19 @@ void FullCodeGenerator::EmitNumberToString(CallRuntime* expr) { } +void FullCodeGenerator::EmitToObject(CallRuntime* expr) { + ZoneList* 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* args = expr->arguments(); DCHECK(args->length() == 1); diff --git a/src/full-codegen/full-codegen.h b/src/full-codegen/full-codegen.h index f90925df4..d83712a56 100644 --- a/src/full-codegen/full-codegen.h +++ b/src/full-codegen/full-codegen.h @@ -531,6 +531,7 @@ class FullCodeGenerator: public AstVisitor { F(RegExpConstructResult) \ F(GetFromCache) \ F(NumberToString) \ + F(ToObject) \ F(DebugIsActive) #define GENERATOR_DECLARATION(Name) void Emit##Name(CallRuntime* call); diff --git a/src/full-codegen/ia32/full-codegen-ia32.cc b/src/full-codegen/ia32/full-codegen-ia32.cc index 93f11ccd6..0d814d618 100644 --- a/src/full-codegen/ia32/full-codegen-ia32.cc +++ b/src/full-codegen/ia32/full-codegen-ia32.cc @@ -1025,8 +1025,8 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) { __ CmpObjectType(eax, FIRST_SPEC_OBJECT_TYPE, ecx); __ j(above_equal, &done_convert, Label::kNear); __ bind(&convert); - __ push(eax); - __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION); + ToObjectStub stub(isolate()); + __ CallStub(&stub); __ bind(&done_convert); PrepareForBailoutForId(stmt->ToObjectId(), TOS_REG); __ push(eax); @@ -3921,6 +3921,19 @@ void FullCodeGenerator::EmitNumberToString(CallRuntime* expr) { } +void FullCodeGenerator::EmitToObject(CallRuntime* expr) { + ZoneList* 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* args = expr->arguments(); DCHECK(args->length() == 1); diff --git a/src/full-codegen/mips/full-codegen-mips.cc b/src/full-codegen/mips/full-codegen-mips.cc index 62bc93576..9e033e2d5 100644 --- a/src/full-codegen/mips/full-codegen-mips.cc +++ b/src/full-codegen/mips/full-codegen-mips.cc @@ -1085,8 +1085,8 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) { __ GetObjectType(a0, a1, a1); __ Branch(&done_convert, ge, a1, Operand(FIRST_SPEC_OBJECT_TYPE)); __ bind(&convert); - __ push(a0); - __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION); + ToObjectStub stub(isolate()); + __ CallStub(&stub); __ mov(a0, v0); __ bind(&done_convert); PrepareForBailoutForId(stmt->ToObjectId(), TOS_REG); @@ -4028,6 +4028,20 @@ void FullCodeGenerator::EmitNumberToString(CallRuntime* expr) { } +void FullCodeGenerator::EmitToObject(CallRuntime* expr) { + ZoneList* 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* args = expr->arguments(); DCHECK(args->length() == 1); diff --git a/src/full-codegen/mips64/full-codegen-mips64.cc b/src/full-codegen/mips64/full-codegen-mips64.cc index 21426b78d..a1d8950fe 100644 --- a/src/full-codegen/mips64/full-codegen-mips64.cc +++ b/src/full-codegen/mips64/full-codegen-mips64.cc @@ -1082,8 +1082,8 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) { __ GetObjectType(a0, a1, a1); __ Branch(&done_convert, ge, a1, Operand(FIRST_SPEC_OBJECT_TYPE)); __ bind(&convert); - __ push(a0); - __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION); + ToObjectStub stub(isolate()); + __ CallStub(&stub); __ mov(a0, v0); __ bind(&done_convert); PrepareForBailoutForId(stmt->ToObjectId(), TOS_REG); @@ -4031,6 +4031,20 @@ void FullCodeGenerator::EmitNumberToString(CallRuntime* expr) { } +void FullCodeGenerator::EmitToObject(CallRuntime* expr) { + ZoneList* 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* args = expr->arguments(); DCHECK(args->length() == 1); diff --git a/src/full-codegen/ppc/full-codegen-ppc.cc b/src/full-codegen/ppc/full-codegen-ppc.cc index 7a754df0b..7234e6abf 100644 --- a/src/full-codegen/ppc/full-codegen-ppc.cc +++ b/src/full-codegen/ppc/full-codegen-ppc.cc @@ -1046,8 +1046,8 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) { __ CompareObjectType(r3, r4, r4, FIRST_SPEC_OBJECT_TYPE); __ bge(&done_convert); __ bind(&convert); - __ push(r3); - __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION); + ToObjectStub stub(isolate()); + __ CallStub(&stub); __ bind(&done_convert); PrepareForBailoutForId(stmt->ToObjectId(), TOS_REG); __ push(r3); @@ -4029,6 +4029,18 @@ void FullCodeGenerator::EmitNumberToString(CallRuntime* expr) { } +void FullCodeGenerator::EmitToObject(CallRuntime* expr) { + ZoneList* 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* args = expr->arguments(); DCHECK(args->length() == 1); diff --git a/src/full-codegen/x64/full-codegen-x64.cc b/src/full-codegen/x64/full-codegen-x64.cc index d8c60ad44..377bf67ee 100644 --- a/src/full-codegen/x64/full-codegen-x64.cc +++ b/src/full-codegen/x64/full-codegen-x64.cc @@ -1039,12 +1039,12 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) { // Convert the object to a JS object. Label convert, done_convert; - __ JumpIfSmi(rax, &convert); + __ JumpIfSmi(rax, &convert, Label::kNear); __ CmpObjectType(rax, FIRST_SPEC_OBJECT_TYPE, rcx); - __ j(above_equal, &done_convert); + __ j(above_equal, &done_convert, Label::kNear); __ bind(&convert); - __ Push(rax); - __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION); + ToObjectStub stub(isolate()); + __ CallStub(&stub); __ bind(&done_convert); PrepareForBailoutForId(stmt->ToObjectId(), TOS_REG); __ Push(rax); @@ -3912,6 +3912,19 @@ void FullCodeGenerator::EmitNumberToString(CallRuntime* expr) { } +void FullCodeGenerator::EmitToObject(CallRuntime* expr) { + ZoneList* 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* args = expr->arguments(); DCHECK(args->length() == 1); diff --git a/src/full-codegen/x87/full-codegen-x87.cc b/src/full-codegen/x87/full-codegen-x87.cc index d4ef7018d..dbe28ae75 100644 --- a/src/full-codegen/x87/full-codegen-x87.cc +++ b/src/full-codegen/x87/full-codegen-x87.cc @@ -1018,8 +1018,8 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) { __ CmpObjectType(eax, FIRST_SPEC_OBJECT_TYPE, ecx); __ j(above_equal, &done_convert, Label::kNear); __ bind(&convert); - __ push(eax); - __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION); + ToObjectStub stub(isolate()); + __ CallStub(&stub); __ bind(&done_convert); PrepareForBailoutForId(stmt->ToObjectId(), TOS_REG); __ push(eax); @@ -3912,6 +3912,19 @@ void FullCodeGenerator::EmitNumberToString(CallRuntime* expr) { } +void FullCodeGenerator::EmitToObject(CallRuntime* expr) { + ZoneList* 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* args = expr->arguments(); DCHECK(args->length() == 1); diff --git a/src/harmony-array-includes.js b/src/harmony-array-includes.js index b133f1ec8..8710d9a30 100644 --- a/src/harmony-array-includes.js +++ b/src/harmony-array-includes.js @@ -16,7 +16,7 @@ var GlobalArray = global.Array; // https://github.com/tc39/Array.prototype.includes // 6e3b78c927aeda20b9d40e81303f9d44596cd904 function ArrayIncludes(searchElement, fromIndex) { - var array = $toObject(this); + var array = TO_OBJECT(this); var len = $toLength(array.length); if (len === 0) { diff --git a/src/harmony-array.js b/src/harmony-array.js index e94134b81..709a6e9e4 100644 --- a/src/harmony-array.js +++ b/src/harmony-array.js @@ -83,7 +83,7 @@ function InnerArrayCopyWithin(target, start, end, array, length) { function ArrayCopyWithin(target, start, end) { CHECK_OBJECT_COERCIBLE(this, "Array.prototype.copyWithin"); - var array = TO_OBJECT_INLINE(this); + var array = TO_OBJECT(this); var length = $toLength(array.length); return InnerArrayCopyWithin(target, start, end, array, length); @@ -103,7 +103,7 @@ function InnerArrayFind(predicate, thisArg, array, length) { for (var i = 0; i < length; i++) { var element = array[i]; - var newThisArg = needs_wrapper ? $toObject(thisArg) : thisArg; + var newThisArg = needs_wrapper ? TO_OBJECT(thisArg) : thisArg; if (%_CallFunction(newThisArg, element, i, array, predicate)) { return element; } @@ -116,7 +116,7 @@ function InnerArrayFind(predicate, thisArg, array, length) { function ArrayFind(predicate, thisArg) { CHECK_OBJECT_COERCIBLE(this, "Array.prototype.find"); - var array = $toObject(this); + var array = TO_OBJECT(this); var length = $toInteger(array.length); return InnerArrayFind(predicate, thisArg, array, length); @@ -136,7 +136,7 @@ function InnerArrayFindIndex(predicate, thisArg, array, length) { for (var i = 0; i < length; i++) { var element = array[i]; - var newThisArg = needs_wrapper ? $toObject(thisArg) : thisArg; + var newThisArg = needs_wrapper ? TO_OBJECT(thisArg) : thisArg; if (%_CallFunction(newThisArg, element, i, array, predicate)) { return i; } @@ -149,7 +149,7 @@ function InnerArrayFindIndex(predicate, thisArg, array, length) { function ArrayFindIndex(predicate, thisArg) { CHECK_OBJECT_COERCIBLE(this, "Array.prototype.findIndex"); - var array = $toObject(this); + var array = TO_OBJECT(this); var length = $toInteger(array.length); return InnerArrayFindIndex(predicate, thisArg, array, length); @@ -187,7 +187,7 @@ function InnerArrayFill(value, start, end, array, length) { function ArrayFill(value, start, end) { CHECK_OBJECT_COERCIBLE(this, "Array.prototype.fill"); - var array = $toObject(this); + var array = TO_OBJECT(this); var length = TO_UINT32(array.length); return InnerArrayFill(value, start, end, array, length); @@ -205,7 +205,7 @@ function AddArrayElement(constructor, array, i, value) { // ES6, draft 10-14-14, section 22.1.2.1 function ArrayFrom(arrayLike, mapfn, receiver) { - var items = $toObject(arrayLike); + var items = TO_OBJECT(arrayLike); var mapping = !IS_UNDEFINED(mapfn); if (mapping) { @@ -215,7 +215,7 @@ function ArrayFrom(arrayLike, mapfn, receiver) { if (IS_NULL(receiver)) { receiver = UNDEFINED; } else if (!IS_UNDEFINED(receiver)) { - receiver = TO_OBJECT_INLINE(receiver); + receiver = TO_OBJECT(receiver); } } } diff --git a/src/harmony-object.js b/src/harmony-object.js index 382f7f425..e0555ba11 100644 --- a/src/harmony-object.js +++ b/src/harmony-object.js @@ -24,7 +24,7 @@ utils.Import(function(from) { // ES6, draft 04-03-15, section 19.1.2.1 function ObjectAssign(target, sources) { - var to = TO_OBJECT_INLINE(target); + var to = TO_OBJECT(target); var argsLen = %_ArgumentsLength(); if (argsLen < 2) return to; @@ -34,7 +34,7 @@ function ObjectAssign(target, sources) { continue; } - var from = TO_OBJECT_INLINE(nextSource); + var from = TO_OBJECT(nextSource); var keys = OwnPropertyKeys(from); var len = keys.length; diff --git a/src/hydrogen.cc b/src/hydrogen.cc index 80546917f..4e8c16d22 100644 --- a/src/hydrogen.cc +++ b/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(receiver); + receiver_is_smi.Then(); + { + // Load native context. + HValue* native_context = BuildGetNativeContext(); + + // Load global Number function. + HValue* constructor = Add( + 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(receiver, nullptr, HObjectAccess::ForMap()); + HValue* receiver_instance_type = Add( + 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( + receiver_instance_type, Add(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( + receiver_instance_type, Add(HEAP_NUMBER_TYPE), Token::EQ); + receiver_is_heap_number.Then(); + { + // Load global Number function. + HValue* constructor = Add( + 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(Heap::kBooleanMapRootIndex); + + IfBuilder receiver_is_boolean(this); + receiver_is_boolean.If(receiver_map, + boolean_map); + receiver_is_boolean.Then(); + { + // Load global Boolean function. + HValue* constructor = Add( + native_context, nullptr, + HObjectAccess::ForContextSlot(Context::BOOLEAN_FUNCTION_INDEX)); + Push(constructor); + } + receiver_is_boolean.Else(); + { + IfBuilder receiver_is_string(this); + receiver_is_string.If( + receiver_instance_type, Add(FIRST_NONSTRING_TYPE), + Token::LT); + receiver_is_string.Then(); + { + // Load global String function. + HValue* constructor = Add( + native_context, nullptr, + HObjectAccess::ForContextSlot(Context::STRING_FUNCTION_INDEX)); + Push(constructor); + } + receiver_is_string.Else(); + { + IfBuilder receiver_is_symbol(this); + receiver_is_symbol.If( + receiver_instance_type, Add(SYMBOL_TYPE), Token::EQ); + receiver_is_symbol.Then(); + { + // Load global Symbol function. + HValue* constructor = Add( + native_context, nullptr, HObjectAccess::ForContextSlot( + Context::SYMBOL_FUNCTION_INDEX)); + Push(constructor); + } + receiver_is_symbol.Else(); + { + IfBuilder receiver_is_float32x4(this); + receiver_is_float32x4.If( + receiver_instance_type, Add(FLOAT32X4_TYPE), + Token::EQ); + receiver_is_float32x4.Then(); + { + // Load global Float32x4 function. + HValue* constructor = Add( + 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( + constructor, nullptr, HObjectAccess::ForPrototypeOrInitialMap()); + // Allocate and initialize a JSValue wrapper. + HValue* value = + BuildAllocate(Add(JSValue::kSize), HType::JSObject(), + JS_VALUE_TYPE, HAllocationMode()); + Add(value, HObjectAccess::ForMap(), + constructor_initial_map); + HValue* empty_fixed_array = Add(Heap::kEmptyFixedArrayRootIndex); + Add(value, HObjectAccess::ForPropertiesPointer(), + empty_fixed_array); + Add(value, HObjectAccess::ForElementsPointer(), + empty_fixed_array); + Add(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, diff --git a/src/hydrogen.h b/src/hydrogen.h index ea74caf73..cc6ddaa96 100644 --- a/src/hydrogen.h +++ b/src/hydrogen.h @@ -1329,6 +1329,7 @@ class HGraphBuilder { bool is_jsarray); HValue* BuildNumberToString(HValue* object, Type* type); + HValue* BuildToObject(HValue* receiver); void BuildJSObjectCheck(HValue* receiver, int bit_field_mask); diff --git a/src/i18n.js b/src/i18n.js index 6b6d4afa6..1028bbb07 100644 --- a/src/i18n.js +++ b/src/i18n.js @@ -251,7 +251,7 @@ function supportedLocalesOf(service, locales, options) { if (IS_UNDEFINED(options)) { options = {}; } else { - options = $toObject(options); + options = TO_OBJECT(options); } var matcher = options.localeMatcher; @@ -717,7 +717,7 @@ function initializeLocaleList(locales) { return freezeArray(seen); } - var o = $toObject(locales); + var o = TO_OBJECT(locales); var len = TO_UINT32(o.length); for (var k = 0; k < len; k++) { @@ -951,7 +951,7 @@ function initializeCollator(collator, locales, options) { return new Intl.Collator(locales, options); } - return initializeCollator($toObject(this), locales, options); + return initializeCollator(TO_OBJECT(this), locales, options); }, DONT_ENUM ); @@ -1192,7 +1192,7 @@ function initializeNumberFormat(numberFormat, locales, options) { return new Intl.NumberFormat(locales, options); } - return initializeNumberFormat($toObject(this), locales, options); + return initializeNumberFormat(TO_OBJECT(this), locales, options); }, DONT_ENUM ); @@ -1444,7 +1444,7 @@ function toDateTimeOptions(options, required, defaults) { if (IS_UNDEFINED(options)) { options = {}; } else { - options = TO_OBJECT_INLINE(options); + options = TO_OBJECT(options); } var needsDefault = true; @@ -1594,7 +1594,7 @@ function initializeDateTimeFormat(dateFormat, locales, options) { return new Intl.DateTimeFormat(locales, options); } - return initializeDateTimeFormat($toObject(this), locales, options); + return initializeDateTimeFormat(TO_OBJECT(this), locales, options); }, DONT_ENUM ); @@ -1814,7 +1814,7 @@ function initializeBreakIterator(iterator, locales, options) { return new Intl.v8BreakIterator(locales, options); } - return initializeBreakIterator($toObject(this), locales, options); + return initializeBreakIterator(TO_OBJECT(this), locales, options); }, DONT_ENUM ); diff --git a/src/ia32/builtins-ia32.cc b/src/ia32/builtins-ia32.cc index 5e42f8469..c4509e200 100644 --- a/src/ia32/builtins-ia32.cc +++ b/src/ia32/builtins-ia32.cc @@ -994,8 +994,9 @@ void Builtins::Generate_FunctionCall(MacroAssembler* masm) { __ SmiTag(eax); __ push(eax); - __ push(ebx); - __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION); + __ mov(eax, ebx); + ToObjectStub stub(masm->isolate()); + __ CallStub(&stub); __ mov(ebx, eax); __ Move(edx, Immediate(0)); // restore @@ -1215,8 +1216,9 @@ static void Generate_ApplyHelper(MacroAssembler* masm, bool targetIsArgument) { __ j(above_equal, &push_receiver); __ bind(&call_to_object); - __ push(ebx); - __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION); + __ mov(eax, ebx); + ToObjectStub stub(masm->isolate()); + __ CallStub(&stub); __ mov(ebx, eax); __ jmp(&push_receiver); diff --git a/src/ia32/code-stubs-ia32.cc b/src/ia32/code-stubs-ia32.cc index 525edea89..bf2630b94 100644 --- a/src/ia32/code-stubs-ia32.cc +++ b/src/ia32/code-stubs-ia32.cc @@ -2093,8 +2093,8 @@ static void EmitWrapCase(MacroAssembler* masm, int argc, Label* cont) { // Wrap the receiver and patch it back onto the stack. { FrameScope frame_scope(masm, StackFrame::INTERNAL); __ push(edi); - __ push(eax); - __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION); + ToObjectStub stub(masm->isolate()); + __ CallStub(&stub); __ pop(edi); } __ mov(Operand(esp, (argc + 1) * kPointerSize), eax); diff --git a/src/ia32/interface-descriptors-ia32.cc b/src/ia32/interface-descriptors-ia32.cc index 61508ee59..496b34e9f 100644 --- a/src/ia32/interface-descriptors-ia32.cc +++ b/src/ia32/interface-descriptors-ia32.cc @@ -103,6 +103,10 @@ void ToNumberDescriptor::InitializePlatformSpecific( } +// static +const Register ToObjectDescriptor::ReceiverRegister() { return eax; } + + void NumberToStringDescriptor::InitializePlatformSpecific( CallInterfaceDescriptorData* data) { Register registers[] = {eax}; diff --git a/src/interface-descriptors.cc b/src/interface-descriptors.cc index 89ee9759a..da9eb2991 100644 --- a/src/interface-descriptors.cc +++ b/src/interface-descriptors.cc @@ -155,6 +155,13 @@ void InstanceofDescriptor::InitializePlatformSpecific( } +void ToObjectDescriptor::InitializePlatformSpecific( + CallInterfaceDescriptorData* data) { + Register registers[] = {ReceiverRegister()}; + data->InitializePlatformSpecific(arraysize(registers), registers); +} + + void MathPowTaggedDescriptor::InitializePlatformSpecific( CallInterfaceDescriptorData* data) { Register registers[] = {exponent()}; diff --git a/src/interface-descriptors.h b/src/interface-descriptors.h index c5e104fba..a01679762 100644 --- a/src/interface-descriptors.h +++ b/src/interface-descriptors.h @@ -24,6 +24,7 @@ class PlatformInterfaceDescriptor; V(FastNewClosure) \ V(FastNewContext) \ V(ToNumber) \ + V(ToObject) \ V(NumberToString) \ V(Typeof) \ V(FastCloneShallowArray) \ @@ -339,6 +340,16 @@ class ToNumberDescriptor : public CallInterfaceDescriptor { }; +class ToObjectDescriptor : public CallInterfaceDescriptor { + public: + enum ParameterIndices { kReceiverIndex }; + + DECLARE_DESCRIPTOR(ToObjectDescriptor, CallInterfaceDescriptor) + + static const Register ReceiverRegister(); +}; + + class NumberToStringDescriptor : public CallInterfaceDescriptor { public: DECLARE_DESCRIPTOR(NumberToStringDescriptor, CallInterfaceDescriptor) diff --git a/src/macros.py b/src/macros.py index 91b413256..de5fe8bfa 100644 --- a/src/macros.py +++ b/src/macros.py @@ -154,7 +154,7 @@ macro TO_INT32(arg) = (%_IsSmi(%IS_VAR(arg)) ? arg : (arg >> 0)); macro TO_UINT32(arg) = (arg >>> 0); macro TO_STRING_INLINE(arg) = (IS_STRING(%IS_VAR(arg)) ? arg : $nonStringToString(arg)); macro TO_NUMBER_INLINE(arg) = (IS_NUMBER(%IS_VAR(arg)) ? arg : $nonNumberToNumber(arg)); -macro TO_OBJECT_INLINE(arg) = (IS_SPEC_OBJECT(%IS_VAR(arg)) ? arg : $toObject(arg)); +macro TO_OBJECT(arg) = (%_ToObject(arg)); macro JSON_NUMBER_TO_STRING(arg) = ((%_IsSmi(%IS_VAR(arg)) || arg - arg == 0) ? %_NumberToString(arg) : "null"); macro HAS_OWN_PROPERTY(arg, index) = (%_CallFunction(arg, index, ObjectHasOwnProperty)); macro SHOULD_CREATE_WRAPPER(functionName, receiver) = (!IS_SPEC_OBJECT(receiver) && %IsSloppyModeFunction(functionName)); diff --git a/src/messages.js b/src/messages.js index 63cefc877..3829eda26 100644 --- a/src/messages.js +++ b/src/messages.js @@ -67,7 +67,7 @@ var GlobalEvalError; function NoSideEffectsObjectToString() { if (IS_UNDEFINED(this) && !IS_UNDETECTABLE(this)) return "[object Undefined]"; if (IS_NULL(this)) return "[object Null]"; - return "[object " + %_ClassOf(TO_OBJECT_INLINE(this)) + "]"; + return "[object " + %_ClassOf(TO_OBJECT(this)) + "]"; } diff --git a/src/mips/builtins-mips.cc b/src/mips/builtins-mips.cc index 711277d1e..ec3e059a1 100644 --- a/src/mips/builtins-mips.cc +++ b/src/mips/builtins-mips.cc @@ -1313,8 +1313,10 @@ void Builtins::Generate_FunctionCall(MacroAssembler* masm) { { FrameScope scope(masm, StackFrame::INTERNAL); __ sll(a0, a0, kSmiTagSize); // Smi tagged. - __ Push(a0, a2); - __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION); + __ push(a0); + __ mov(a0, a2); + ToObjectStub stub(masm->isolate()); + __ CallStub(&stub); __ mov(a2, v0); __ pop(a0); @@ -1548,8 +1550,8 @@ static void Generate_ApplyHelper(MacroAssembler* masm, bool targetIsArgument) { // Convert the receiver to a regular object. // a0: receiver __ bind(&call_to_object); - __ push(a0); - __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION); + ToObjectStub stub(masm->isolate()); + __ CallStub(&stub); __ mov(a0, v0); // Put object in a0 to match other paths to push_receiver. __ Branch(&push_receiver); diff --git a/src/mips/code-stubs-mips.cc b/src/mips/code-stubs-mips.cc index 5ebb70ed8..daff32fe9 100644 --- a/src/mips/code-stubs-mips.cc +++ b/src/mips/code-stubs-mips.cc @@ -2675,8 +2675,10 @@ static void EmitSlowCase(MacroAssembler* masm, static void EmitWrapCase(MacroAssembler* masm, int argc, Label* cont) { // Wrap the receiver and patch it back onto the stack. { FrameScope frame_scope(masm, StackFrame::INTERNAL); - __ Push(a1, a3); - __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION); + __ Push(a1); + __ mov(a0, a3); + ToObjectStub stub(masm->isolate()); + __ CallStub(&stub); __ pop(a1); } __ Branch(USE_DELAY_SLOT, cont); diff --git a/src/mips/interface-descriptors-mips.cc b/src/mips/interface-descriptors-mips.cc index f0618ad98..df3652052 100644 --- a/src/mips/interface-descriptors-mips.cc +++ b/src/mips/interface-descriptors-mips.cc @@ -95,6 +95,10 @@ void ToNumberDescriptor::InitializePlatformSpecific( } +// static +const Register ToObjectDescriptor::ReceiverRegister() { return a0; } + + void NumberToStringDescriptor::InitializePlatformSpecific( CallInterfaceDescriptorData* data) { Register registers[] = {a0}; diff --git a/src/mips64/builtins-mips64.cc b/src/mips64/builtins-mips64.cc index 088893910..3fb288bf0 100644 --- a/src/mips64/builtins-mips64.cc +++ b/src/mips64/builtins-mips64.cc @@ -1309,8 +1309,10 @@ void Builtins::Generate_FunctionCall(MacroAssembler* masm) { { FrameScope scope(masm, StackFrame::INTERNAL); __ SmiTag(a0); - __ Push(a0, a2); - __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION); + __ Push(a0); + __ mov(a0, a2); + ToObjectStub stub(masm->isolate()); + __ CallStub(&stub); __ mov(a2, v0); __ pop(a0); @@ -1545,8 +1547,8 @@ static void Generate_ApplyHelper(MacroAssembler* masm, bool targetIsArgument) { // Convert the receiver to a regular object. // a0: receiver __ bind(&call_to_object); - __ push(a0); - __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION); + ToObjectStub stub(masm->isolate()); + __ CallStub(&stub); __ mov(a0, v0); // Put object in a0 to match other paths to push_receiver. __ Branch(&push_receiver); diff --git a/src/mips64/code-stubs-mips64.cc b/src/mips64/code-stubs-mips64.cc index 494d9474f..8b46e4c72 100644 --- a/src/mips64/code-stubs-mips64.cc +++ b/src/mips64/code-stubs-mips64.cc @@ -2714,8 +2714,10 @@ static void EmitSlowCase(MacroAssembler* masm, static void EmitWrapCase(MacroAssembler* masm, int argc, Label* cont) { // Wrap the receiver and patch it back onto the stack. { FrameScope frame_scope(masm, StackFrame::INTERNAL); - __ Push(a1, a3); - __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION); + __ Push(a1); + __ mov(a0, a3); + ToObjectStub stub(masm->isolate()); + __ CallStub(&stub); __ pop(a1); } __ Branch(USE_DELAY_SLOT, cont); diff --git a/src/mips64/interface-descriptors-mips64.cc b/src/mips64/interface-descriptors-mips64.cc index 87c8ffbc8..1498d924d 100644 --- a/src/mips64/interface-descriptors-mips64.cc +++ b/src/mips64/interface-descriptors-mips64.cc @@ -95,6 +95,10 @@ void ToNumberDescriptor::InitializePlatformSpecific( } +// static +const Register ToObjectDescriptor::ReceiverRegister() { return a0; } + + void NumberToStringDescriptor::InitializePlatformSpecific( CallInterfaceDescriptorData* data) { Register registers[] = {a0}; diff --git a/src/ppc/builtins-ppc.cc b/src/ppc/builtins-ppc.cc index bdcf40614..4dc06fe3b 100644 --- a/src/ppc/builtins-ppc.cc +++ b/src/ppc/builtins-ppc.cc @@ -1338,8 +1338,10 @@ void Builtins::Generate_FunctionCall(MacroAssembler* masm) { // Enter an internal frame in order to preserve argument count. FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL); __ SmiTag(r3); - __ Push(r3, r5); - __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION); + __ Push(r3); + __ mr(r3, r5); + ToObjectStub stub(masm->isolate()); + __ CallStub(&stub); __ mr(r5, r3); __ pop(r3); @@ -1592,8 +1594,8 @@ static void Generate_ApplyHelper(MacroAssembler* masm, bool targetIsArgument) { // Convert the receiver to a regular object. // r3: receiver __ bind(&call_to_object); - __ push(r3); - __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION); + ToObjectStub stub(masm->isolate()); + __ CallStub(&stub); __ b(&push_receiver); __ bind(&use_global_proxy); diff --git a/src/ppc/code-stubs-ppc.cc b/src/ppc/code-stubs-ppc.cc index 015a6ef1a..59aa8b182 100644 --- a/src/ppc/code-stubs-ppc.cc +++ b/src/ppc/code-stubs-ppc.cc @@ -2726,8 +2726,10 @@ static void EmitWrapCase(MacroAssembler* masm, int argc, Label* cont) { // Wrap the receiver and patch it back onto the stack. { FrameAndConstantPoolScope frame_scope(masm, StackFrame::INTERNAL); - __ Push(r4, r6); - __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION); + __ push(r4); + __ mr(r3, r6); + ToObjectStub stub(masm->isolate()); + __ CallStub(&stub); __ pop(r4); } __ StoreP(r3, MemOperand(sp, argc * kPointerSize), r0); diff --git a/src/ppc/interface-descriptors-ppc.cc b/src/ppc/interface-descriptors-ppc.cc index c59fc56d2..8b605111c 100644 --- a/src/ppc/interface-descriptors-ppc.cc +++ b/src/ppc/interface-descriptors-ppc.cc @@ -95,6 +95,10 @@ void ToNumberDescriptor::InitializePlatformSpecific( } +// static +const Register ToObjectDescriptor::ReceiverRegister() { return r3; } + + void NumberToStringDescriptor::InitializePlatformSpecific( CallInterfaceDescriptorData* data) { Register registers[] = {r3}; diff --git a/src/runtime.js b/src/runtime.js index 63a733fcb..000d49756 100644 --- a/src/runtime.js +++ b/src/runtime.js @@ -58,7 +58,6 @@ var APPLY_PREPARE; var REFLECT_APPLY_PREPARE; var REFLECT_CONSTRUCT_PREPARE; var STACK_OVERFLOW; -var TO_OBJECT; var TO_NUMBER; var TO_STRING; var TO_NAME; @@ -76,7 +75,6 @@ var $toInteger; var $toLength; var $toName; var $toNumber; -var $toObject; var $toPositiveInteger; var $toPrimitive; var $toString; @@ -512,7 +510,7 @@ SHR_STRONG = function SHR_STRONG(y) { // ECMA-262, section 11.4.1, page 46. DELETE = function DELETE(key, language_mode) { - return %DeleteProperty(%$toObject(this), key, language_mode); + return %DeleteProperty(TO_OBJECT(this), key, language_mode); } @@ -730,12 +728,6 @@ STACK_OVERFLOW = function STACK_OVERFLOW(length) { } -// Convert the receiver to an object - forward to ToObject. -TO_OBJECT = function TO_OBJECT() { - return %$toObject(this); -} - - // Convert the receiver to a number - forward to ToNumber. TO_NUMBER = function TO_NUMBER() { return %$toNumber(this); @@ -832,20 +824,6 @@ function ToName(x) { } -// ECMA-262, section 9.9, page 36. -function ToObject(x) { - if (IS_STRING(x)) return new GlobalString(x); - if (IS_NUMBER(x)) return new GlobalNumber(x); - if (IS_BOOLEAN(x)) return new GlobalBoolean(x); - if (IS_SYMBOL(x)) return %NewSymbolWrapper(x); - if (IS_FLOAT32X4(x)) return %NewFloat32x4Wrapper(x); - if (IS_NULL_OR_UNDEFINED(x) && !IS_UNDETECTABLE(x)) { - throw MakeTypeError(kUndefinedOrNullToObject); - } - return x; -} - - // ECMA-262, section 9.4, page 34. function ToInteger(x) { if (%_IsSmi(x)) return x; @@ -1006,7 +984,6 @@ $toInteger = ToInteger; $toLength = ToLength; $toName = ToName; $toNumber = ToNumber; -$toObject = ToObject; $toPositiveInteger = ToPositiveInteger; $toPrimitive = ToPrimitive; $toString = ToString; diff --git a/src/runtime/runtime-object.cc b/src/runtime/runtime-object.cc index 255dbf073..04f15bea1 100644 --- a/src/runtime/runtime-object.cc +++ b/src/runtime/runtime-object.cc @@ -1461,5 +1461,19 @@ RUNTIME_FUNCTION(Runtime_DefineSetterPropertyUnchecked) { setter, attrs)); return isolate->heap()->undefined_value(); } + + +RUNTIME_FUNCTION(Runtime_ToObject) { + HandleScope scope(isolate); + DCHECK_EQ(1, args.length()); + CONVERT_ARG_HANDLE_CHECKED(Object, object, 0); + Handle receiver; + if (JSReceiver::ToObject(isolate, object).ToHandle(&receiver)) { + return *receiver; + } + THROW_NEW_ERROR_RETURN_FAILURE( + isolate, NewTypeError(MessageTemplate::kUndefinedOrNullToObject)); +} + } // namespace internal } // namespace v8 diff --git a/src/runtime/runtime-simd.cc b/src/runtime/runtime-simd.cc index 5c60ad501..12c317147 100644 --- a/src/runtime/runtime-simd.cc +++ b/src/runtime/runtime-simd.cc @@ -33,14 +33,6 @@ NumberTo##type##Component(*y), NumberTo##type##Component(*z)); \ } -#define SIMD_CREATE_WRAPPER_FUNCTION(type) \ - RUNTIME_FUNCTION(Runtime_New##type##Wrapper) { \ - HandleScope scope(isolate); \ - DCHECK(args.length() == 1); \ - CONVERT_ARG_HANDLE_CHECKED(type, value, 0); \ - return *Object::ToObject(isolate, value).ToHandleChecked(); \ - } - #define SIMD_CHECK_FUNCTION(type) \ RUNTIME_FUNCTION(Runtime_##type##Check) { \ HandleScope scope(isolate); \ @@ -101,7 +93,6 @@ #define SIMD4_FUNCTIONS(type) \ SIMD4_CREATE_FUNCTION(type) \ - SIMD_CREATE_WRAPPER_FUNCTION(type) \ SIMD_CHECK_FUNCTION(type) \ SIMD4_EXTRACT_LANE_FUNCTION(type) \ SIMD4_EQUALS_FUNCTION(type) \ @@ -125,5 +116,6 @@ inline bool Equals(float x, float y) { return x == y; } } // namespace SIMD4_FUNCTIONS(Float32x4) -} -} // namespace v8::internal + +} // namespace internal +} // namespace v8 diff --git a/src/runtime/runtime-symbol.cc b/src/runtime/runtime-symbol.cc index 412ee0ae3..bd4f3ed23 100644 --- a/src/runtime/runtime-symbol.cc +++ b/src/runtime/runtime-symbol.cc @@ -51,14 +51,6 @@ RUNTIME_FUNCTION(Runtime_CreateGlobalPrivateSymbol) { } -RUNTIME_FUNCTION(Runtime_NewSymbolWrapper) { - HandleScope scope(isolate); - DCHECK(args.length() == 1); - CONVERT_ARG_HANDLE_CHECKED(Symbol, symbol, 0); - return *Object::ToObject(isolate, symbol).ToHandleChecked(); -} - - RUNTIME_FUNCTION(Runtime_SymbolDescription) { SealHandleScope shs(isolate); DCHECK(args.length() == 1); diff --git a/src/runtime/runtime.h b/src/runtime/runtime.h index 6d7c8ccbc..f89618dac 100644 --- a/src/runtime/runtime.h +++ b/src/runtime/runtime.h @@ -497,7 +497,8 @@ namespace internal { F(IsStrong, 1, 1) \ F(ClassOf, 1, 1) \ F(DefineGetterPropertyUnchecked, 4, 1) \ - F(DefineSetterPropertyUnchecked, 4, 1) + F(DefineSetterPropertyUnchecked, 4, 1) \ + F(ToObject, 1, 1) #define FOR_EACH_INTRINSIC_OBSERVE(F) \ @@ -570,7 +571,6 @@ namespace internal { #define FOR_EACH_INTRINSIC_SIMD(F) \ F(CreateFloat32x4, 4, 1) \ - F(NewFloat32x4Wrapper, 1, 1) \ F(Float32x4Check, 1, 1) \ F(Float32x4ExtractLane, 2, 1) \ F(Float32x4Equals, 2, 1) \ @@ -620,7 +620,6 @@ namespace internal { F(CreateSymbol, 1, 1) \ F(CreatePrivateSymbol, 1, 1) \ F(CreateGlobalPrivateSymbol, 1, 1) \ - F(NewSymbolWrapper, 1, 1) \ F(SymbolDescription, 1, 1) \ F(SymbolRegistry, 0, 1) \ F(SymbolIsPrivate, 1, 1) diff --git a/src/string-iterator.js b/src/string-iterator.js index 536430ee8..bb392ef10 100644 --- a/src/string-iterator.js +++ b/src/string-iterator.js @@ -41,7 +41,7 @@ function CreateStringIterator(string) { // 21.1.5.2.1 %StringIteratorPrototype%.next( ) function StringIteratorNext() { - var iterator = $toObject(this); + var iterator = TO_OBJECT(this); if (!HAS_DEFINED_PRIVATE(iterator, stringIteratorNextIndexSymbol)) { throw MakeTypeError(kIncompatibleMethodReceiver, diff --git a/src/string.js b/src/string.js index 387e5bef5..322e5ae6d 100644 --- a/src/string.js +++ b/src/string.js @@ -1112,8 +1112,8 @@ function StringFromCodePoint(_) { // length = 1 function StringRaw(callSite) { // TODO(caitp): Use rest parameters when implemented var numberOfSubstitutions = %_ArgumentsLength(); - var cooked = $toObject(callSite); - var raw = $toObject(cooked.raw); + var cooked = TO_OBJECT(callSite); + var raw = TO_OBJECT(cooked.raw); var literalSegments = $toLength(raw.length); if (literalSegments <= 0) return ""; diff --git a/src/symbol.js b/src/symbol.js index 8ac7fe701..5c5ec007a 100644 --- a/src/symbol.js +++ b/src/symbol.js @@ -78,7 +78,7 @@ function SymbolKeyFor(symbol) { // ES6 19.1.2.8 function ObjectGetOwnPropertySymbols(obj) { - obj = $toObject(obj); + obj = TO_OBJECT(obj); // TODO(arv): Proxies use a shared trap for String and Symbol keys. diff --git a/src/v8natives.js b/src/v8natives.js index 92769e25d..542d70966 100644 --- a/src/v8natives.js +++ b/src/v8natives.js @@ -141,7 +141,7 @@ utils.InstallFunctions(global, DONT_ENUM, [ function ObjectToString() { if (IS_UNDEFINED(this) && !IS_UNDETECTABLE(this)) return "[object Undefined]"; if (IS_NULL(this)) return "[object Null]"; - var O = TO_OBJECT_INLINE(this); + var O = TO_OBJECT(this); var builtinTag = %_ClassOf(O); var tag; @@ -168,14 +168,14 @@ function ObjectToLocaleString() { // ECMA-262 - 15.2.4.4 function ObjectValueOf() { - return TO_OBJECT_INLINE(this); + return TO_OBJECT(this); } // ECMA-262 - 15.2.4.5 function ObjectHasOwnProperty(value) { var name = $toName(value); - var object = TO_OBJECT_INLINE(this); + var object = TO_OBJECT(this); if (%_IsJSProxy(object)) { // TODO(rossberg): adjust once there is a story for symbols vs proxies. @@ -206,7 +206,7 @@ function ObjectPropertyIsEnumerable(V) { var desc = GetOwnPropertyJS(this, P); return IS_UNDEFINED(desc) ? false : desc.isEnumerable(); } - return %IsPropertyEnumerable(TO_OBJECT_INLINE(this), P); + return %IsPropertyEnumerable(TO_OBJECT(this), P); } @@ -223,7 +223,7 @@ function ObjectDefineGetter(name, fun) { desc.setGet(fun); desc.setEnumerable(true); desc.setConfigurable(true); - DefineOwnProperty(TO_OBJECT_INLINE(receiver), $toName(name), desc, false); + DefineOwnProperty(TO_OBJECT(receiver), $toName(name), desc, false); } @@ -232,7 +232,7 @@ function ObjectLookupGetter(name) { if (receiver == null && !IS_UNDETECTABLE(receiver)) { receiver = %GlobalProxy(ObjectLookupGetter); } - return %LookupAccessor(TO_OBJECT_INLINE(receiver), $toName(name), GETTER); + return %LookupAccessor(TO_OBJECT(receiver), $toName(name), GETTER); } @@ -248,7 +248,7 @@ function ObjectDefineSetter(name, fun) { desc.setSet(fun); desc.setEnumerable(true); desc.setConfigurable(true); - DefineOwnProperty(TO_OBJECT_INLINE(receiver), $toName(name), desc, false); + DefineOwnProperty(TO_OBJECT(receiver), $toName(name), desc, false); } @@ -257,12 +257,12 @@ function ObjectLookupSetter(name) { if (receiver == null && !IS_UNDETECTABLE(receiver)) { receiver = %GlobalProxy(ObjectLookupSetter); } - return %LookupAccessor(TO_OBJECT_INLINE(receiver), $toName(name), SETTER); + return %LookupAccessor(TO_OBJECT(receiver), $toName(name), SETTER); } function ObjectKeys(obj) { - obj = TO_OBJECT_INLINE(obj); + obj = TO_OBJECT(obj); if (%_IsJSProxy(obj)) { var handler = %GetHandler(obj); var names = CallTrap0(handler, "keys", ProxyDerivedKeysTrap); @@ -579,7 +579,7 @@ function GetOwnPropertyJS(obj, v) { // GetOwnProperty returns an array indexed by the constants // defined in macros.py. // If p is not a property on obj undefined is returned. - var props = %GetOwnProperty(TO_OBJECT_INLINE(obj), p); + var props = %GetOwnProperty(TO_OBJECT(obj), p); return ConvertDescriptorArrayToDescriptor(props); } @@ -868,7 +868,7 @@ function DefineOwnPropertyFromAPI(obj, p, value, desc) { // ES6 section 19.1.2.9 function ObjectGetPrototypeOf(obj) { - return %_GetPrototype(TO_OBJECT_INLINE(obj)); + return %_GetPrototype(TO_OBJECT(obj)); } // ES6 section 19.1.2.19. @@ -889,7 +889,7 @@ function ObjectSetPrototypeOf(obj, proto) { // ES6 section 19.1.2.6 function ObjectGetOwnPropertyDescriptor(obj, p) { - var desc = GetOwnPropertyJS(TO_OBJECT_INLINE(obj), p); + var desc = GetOwnPropertyJS(TO_OBJECT(obj), p); return FromPropertyDescriptor(desc); } @@ -1001,7 +1001,7 @@ function OwnPropertyKeys(obj) { // ES5 section 15.2.3.4. function ObjectGetOwnPropertyNames(obj) { - obj = TO_OBJECT_INLINE(obj); + obj = TO_OBJECT(obj); // Special handling for proxies. if (%_IsJSProxy(obj)) { var handler = %GetHandler(obj); @@ -1093,7 +1093,7 @@ function ObjectDefineProperties(obj, properties) { if (!IS_SPEC_OBJECT(obj)) { throw MakeTypeError(kCalledOnNonObject, "Object.defineProperties"); } - var props = TO_OBJECT_INLINE(properties); + var props = TO_OBJECT(properties); var names = GetOwnEnumerablePropertyNames(props); var descriptors = new InternalArray(); for (var i = 0; i < names.length; i++) { @@ -1263,7 +1263,7 @@ function ObjectIs(obj1, obj2) { // ECMA-262, Edition 6, section B.2.2.1.1 function ObjectGetProto() { - return %_GetPrototype(TO_OBJECT_INLINE(this)); + return %_GetPrototype(TO_OBJECT(this)); } @@ -1280,10 +1280,10 @@ function ObjectSetProto(proto) { function ObjectConstructor(x) { if (%_IsConstructCall()) { if (x == null) return this; - return TO_OBJECT_INLINE(x); + return TO_OBJECT(x); } else { if (x == null) return { }; - return TO_OBJECT_INLINE(x); + return TO_OBJECT(x); } } diff --git a/src/x64/builtins-x64.cc b/src/x64/builtins-x64.cc index 8e782158c..c8b132105 100644 --- a/src/x64/builtins-x64.cc +++ b/src/x64/builtins-x64.cc @@ -1053,8 +1053,9 @@ void Builtins::Generate_FunctionCall(MacroAssembler* masm) { __ Integer32ToSmi(rax, rax); __ Push(rax); - __ Push(rbx); - __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION); + __ movp(rax, rbx); + ToObjectStub stub(masm->isolate()); + __ CallStub(&stub); __ movp(rbx, rax); __ Set(rdx, 0); // indicate regular JS_FUNCTION @@ -1274,8 +1275,9 @@ static void Generate_ApplyHelper(MacroAssembler* masm, bool targetIsArgument) { // Convert the receiver to an object. __ bind(&call_to_object); - __ Push(rbx); - __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION); + __ movp(rax, rbx); + ToObjectStub stub(masm->isolate()); + __ CallStub(&stub); __ movp(rbx, rax); __ jmp(&push_receiver, Label::kNear); diff --git a/src/x64/code-stubs-x64.cc b/src/x64/code-stubs-x64.cc index 7d717015a..3ab60c8d8 100644 --- a/src/x64/code-stubs-x64.cc +++ b/src/x64/code-stubs-x64.cc @@ -1964,8 +1964,8 @@ static void EmitWrapCase(MacroAssembler* masm, // Wrap the receiver and patch it back onto the stack. { FrameScope frame_scope(masm, StackFrame::INTERNAL); __ Push(rdi); - __ Push(rax); - __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION); + ToObjectStub stub(masm->isolate()); + __ CallStub(&stub); __ Pop(rdi); } __ movp(args->GetReceiverOperand(), rax); diff --git a/src/x64/interface-descriptors-x64.cc b/src/x64/interface-descriptors-x64.cc index da5e506b2..9fd4470e0 100644 --- a/src/x64/interface-descriptors-x64.cc +++ b/src/x64/interface-descriptors-x64.cc @@ -103,6 +103,10 @@ void ToNumberDescriptor::InitializePlatformSpecific( } +// static +const Register ToObjectDescriptor::ReceiverRegister() { return rax; } + + void NumberToStringDescriptor::InitializePlatformSpecific( CallInterfaceDescriptorData* data) { Register registers[] = {rax}; diff --git a/src/x87/builtins-x87.cc b/src/x87/builtins-x87.cc index da427e22f..f6cf7a165 100644 --- a/src/x87/builtins-x87.cc +++ b/src/x87/builtins-x87.cc @@ -994,8 +994,9 @@ void Builtins::Generate_FunctionCall(MacroAssembler* masm) { __ SmiTag(eax); __ push(eax); - __ push(ebx); - __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION); + __ mov(eax, ebx); + ToObjectStub stub(masm->isolate()); + __ CallStub(&stub); __ mov(ebx, eax); __ Move(edx, Immediate(0)); // restore @@ -1215,8 +1216,9 @@ static void Generate_ApplyHelper(MacroAssembler* masm, bool targetIsArgument) { __ j(above_equal, &push_receiver); __ bind(&call_to_object); - __ push(ebx); - __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION); + __ mov(eax, ebx); + ToObjectStub stub(masm->isolate()); + __ CallStub(&stub); __ mov(ebx, eax); __ jmp(&push_receiver); diff --git a/src/x87/code-stubs-x87.cc b/src/x87/code-stubs-x87.cc index e70f9c85b..cdcbaf940 100644 --- a/src/x87/code-stubs-x87.cc +++ b/src/x87/code-stubs-x87.cc @@ -1800,8 +1800,8 @@ static void EmitWrapCase(MacroAssembler* masm, int argc, Label* cont) { // Wrap the receiver and patch it back onto the stack. { FrameScope frame_scope(masm, StackFrame::INTERNAL); __ push(edi); - __ push(eax); - __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION); + ToObjectStub stub(masm->isolate()); + __ CallStub(&stub); __ pop(edi); } __ mov(Operand(esp, (argc + 1) * kPointerSize), eax); diff --git a/src/x87/interface-descriptors-x87.cc b/src/x87/interface-descriptors-x87.cc index dacbf1061..7e03fac07 100644 --- a/src/x87/interface-descriptors-x87.cc +++ b/src/x87/interface-descriptors-x87.cc @@ -103,6 +103,10 @@ void ToNumberDescriptor::InitializePlatformSpecific( } +// static +const Register ToObjectDescriptor::ReceiverRegister() { return eax; } + + void NumberToStringDescriptor::InitializePlatformSpecific( CallInterfaceDescriptorData* data) { Register registers[] = {eax};