[stubs] Unify (and optimize) implementation of ToObject.
authorbmeurer <bmeurer@chromium.org>
Fri, 31 Jul 2015 12:25:28 +0000 (05:25 -0700)
committerCommit bot <commit-bot@chromium.org>
Fri, 31 Jul 2015 12:25:44 +0000 (12:25 +0000)
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}

72 files changed:
include/v8.h
src/arm/builtins-arm.cc
src/arm/code-stubs-arm.cc
src/arm/interface-descriptors-arm.cc
src/arm64/builtins-arm64.cc
src/arm64/code-stubs-arm64.cc
src/arm64/interface-descriptors-arm64.cc
src/array-iterator.js
src/array.js
src/bootstrapper.cc
src/builtins.h
src/code-factory.cc
src/code-factory.h
src/code-stubs-hydrogen.cc
src/code-stubs.cc
src/code-stubs.h
src/collection.js
src/compiler/js-generic-lowering.cc
src/compiler/js-intrinsic-lowering.cc
src/compiler/js-intrinsic-lowering.h
src/compiler/linkage.cc
src/compiler/typer.cc
src/contexts.h
src/date.js
src/deoptimizer.h
src/execution.cc
src/full-codegen/arm/full-codegen-arm.cc
src/full-codegen/arm64/full-codegen-arm64.cc
src/full-codegen/full-codegen.h
src/full-codegen/ia32/full-codegen-ia32.cc
src/full-codegen/mips/full-codegen-mips.cc
src/full-codegen/mips64/full-codegen-mips64.cc
src/full-codegen/ppc/full-codegen-ppc.cc
src/full-codegen/x64/full-codegen-x64.cc
src/full-codegen/x87/full-codegen-x87.cc
src/harmony-array-includes.js
src/harmony-array.js
src/harmony-object.js
src/hydrogen.cc
src/hydrogen.h
src/i18n.js
src/ia32/builtins-ia32.cc
src/ia32/code-stubs-ia32.cc
src/ia32/interface-descriptors-ia32.cc
src/interface-descriptors.cc
src/interface-descriptors.h
src/macros.py
src/messages.js
src/mips/builtins-mips.cc
src/mips/code-stubs-mips.cc
src/mips/interface-descriptors-mips.cc
src/mips64/builtins-mips64.cc
src/mips64/code-stubs-mips64.cc
src/mips64/interface-descriptors-mips64.cc
src/ppc/builtins-ppc.cc
src/ppc/code-stubs-ppc.cc
src/ppc/interface-descriptors-ppc.cc
src/runtime.js
src/runtime/runtime-object.cc
src/runtime/runtime-simd.cc
src/runtime/runtime-symbol.cc
src/runtime/runtime.h
src/string-iterator.js
src/string.js
src/symbol.js
src/v8natives.js
src/x64/builtins-x64.cc
src/x64/code-stubs-x64.cc
src/x64/interface-descriptors-x64.cc
src/x87/builtins-x87.cc
src/x87/code-stubs-x87.cc
src/x87/interface-descriptors-x87.cc

index 50f0f5f..0bcb311 100644 (file)
@@ -6913,7 +6913,7 @@ class Internals {
   static const int kJSObjectHeaderSize = 3 * kApiPointerSize;
   static const int kFixedArrayHeaderSize = 2 * kApiPointerSize;
   static const int kContextHeaderSize = 2 * kApiPointerSize;
-  static const int kContextEmbedderDataIndex = 82;
+  static const int kContextEmbedderDataIndex = 81;
   static const int kFullStringRepresentationMask = 0x07;
   static const int kStringEncodingMask = 0x4;
   static const int kExternalTwoByteRepresentationTag = 0x02;
index b33a195..113510c 100644 (file)
@@ -1319,8 +1319,9 @@ void Builtins::Generate_FunctionCall(MacroAssembler* masm) {
       __ SmiTag(r0);
       __ push(r0);
 
-      __ push(r2);
-      __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
+      __ mov(r0, r2);
+      ToObjectStub stub(masm->isolate());
+      __ CallStub(&stub);
       __ mov(r2, r0);
 
       __ pop(r0);
@@ -1556,8 +1557,8 @@ static void Generate_ApplyHelper(MacroAssembler* masm, bool targetIsArgument) {
     // Convert the receiver to a regular object.
     // r0: receiver
     __ bind(&call_to_object);
-    __ push(r0);
-    __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
+    ToObjectStub stub(masm->isolate());
+    __ CallStub(&stub);
     __ b(&push_receiver);
 
     __ bind(&use_global_proxy);
index cc090d5..80d01a1 100644 (file)
@@ -2547,8 +2547,10 @@ static void EmitSlowCase(MacroAssembler* masm,
 static void EmitWrapCase(MacroAssembler* masm, int argc, Label* cont) {
   // Wrap the receiver and patch it back onto the stack.
   { FrameAndConstantPoolScope frame_scope(masm, StackFrame::INTERNAL);
-    __ Push(r1, r3);
-    __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
+    __ push(r1);
+    __ mov(r0, r3);
+    ToObjectStub stub(masm->isolate());
+    __ CallStub(&stub);
     __ pop(r1);
   }
   __ str(r0, MemOperand(sp, argc * kPointerSize));
index e54dd5c..ddaf9e5 100644 (file)
@@ -95,6 +95,10 @@ void ToNumberDescriptor::InitializePlatformSpecific(
 }
 
 
+// static
+const Register ToObjectDescriptor::ReceiverRegister() { return r0; }
+
+
 void NumberToStringDescriptor::InitializePlatformSpecific(
     CallInterfaceDescriptorData* data) {
   Register registers[] = {r0};
index d93b5ad..0cb9561 100644 (file)
@@ -1355,8 +1355,10 @@ void Builtins::Generate_FunctionCall(MacroAssembler* masm) {
       FrameScope scope(masm, StackFrame::INTERNAL);
       __ SmiTag(argc);
 
-      __ Push(argc, receiver);
-      __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
+      __ Push(argc);
+      __ Mov(x0, receiver);
+      ToObjectStub stub(masm->isolate());
+      __ CallStub(&stub);
       __ Mov(receiver, x0);
 
       __ Pop(argc);
@@ -1582,8 +1584,9 @@ static void Generate_ApplyHelper(MacroAssembler* masm, bool targetIsArgument) {
 
     // Call a builtin to convert the receiver to a regular object.
     __ Bind(&convert_receiver_to_object);
-    __ Push(receiver);
-    __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
+    __ Mov(x0, receiver);
+    ToObjectStub stub(masm->isolate());
+    __ CallStub(&stub);
     __ Mov(receiver, x0);
     __ B(&push_receiver);
 
index d349383..b103641 100644 (file)
@@ -2921,8 +2921,10 @@ static void EmitSlowCase(MacroAssembler* masm,
 static void EmitWrapCase(MacroAssembler* masm, int argc, Label* cont) {
   // Wrap the receiver and patch it back onto the stack.
   { FrameScope frame_scope(masm, StackFrame::INTERNAL);
-    __ Push(x1, x3);
-    __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
+    __ Push(x1);
+    __ Mov(x0, x3);
+    ToObjectStub stub(masm->isolate());
+    __ CallStub(&stub);
     __ Pop(x1);
   }
   __ Poke(x0, argc * kPointerSize);
index d344783..c8cbd31 100644 (file)
@@ -104,6 +104,10 @@ void ToNumberDescriptor::InitializePlatformSpecific(
 }
 
 
+// static
+const Register ToObjectDescriptor::ReceiverRegister() { return x0; }
+
+
 void NumberToStringDescriptor::InitializePlatformSpecific(
     CallInterfaceDescriptorData* data) {
   // x0: value
index 965e672..24a9ba5 100644 (file)
@@ -45,7 +45,7 @@ function ArrayIterator() {}
 
 // 15.4.5.1 CreateArrayIterator Abstract Operation
 function CreateArrayIterator(array, kind) {
-  var object = $toObject(array);
+  var object = TO_OBJECT(array);
   var iterator = new ArrayIterator;
   SET_PRIVATE(iterator, arrayIteratorObjectSymbol, object);
   SET_PRIVATE(iterator, arrayIteratorNextIndexSymbol, 0);
@@ -68,7 +68,7 @@ function ArrayIteratorIterator() {
 
 // 15.4.5.2.2 ArrayIterator.prototype.next( )
 function ArrayIteratorNext() {
-  var iterator = $toObject(this);
+  var iterator = TO_OBJECT(this);
 
   if (!HAS_DEFINED_PRIVATE(iterator, arrayIteratorNextIndexSymbol)) {
     throw MakeTypeError(kIncompatibleMethodReceiver,
index e0cc069..7d0fdca 100644 (file)
@@ -227,7 +227,7 @@ function ConvertToLocaleString(e) {
     // According to ES5, section 15.4.4.3, the toLocaleString conversion
     // must throw a TypeError if ToObject(e).toLocaleString isn't
     // callable.
-    var e_obj = $toObject(e);
+    var e_obj = TO_OBJECT(e);
     return $toString(e_obj.toLocaleString());
   }
 }
@@ -388,7 +388,7 @@ function ArrayToString() {
     }
     array = this;
   } else {
-    array = $toObject(this);
+    array = TO_OBJECT(this);
     func = array.join;
   }
   if (!IS_SPEC_FUNCTION(func)) {
@@ -406,7 +406,7 @@ function InnerArrayToLocaleString(array, length) {
 
 
 function ArrayToLocaleString() {
-  var array = $toObject(this);
+  var array = TO_OBJECT(this);
   var arrayLen = array.length;
   return InnerArrayToLocaleString(array, arrayLen);
 }
@@ -437,7 +437,7 @@ function InnerArrayJoin(separator, array, length) {
 function ArrayJoin(separator) {
   CHECK_OBJECT_COERCIBLE(this, "Array.prototype.join");
 
-  var array = TO_OBJECT_INLINE(this);
+  var array = TO_OBJECT(this);
   var length = TO_UINT32(array.length);
 
   return InnerArrayJoin(separator, array, length);
@@ -466,7 +466,7 @@ function ObservedArrayPop(n) {
 function ArrayPop() {
   CHECK_OBJECT_COERCIBLE(this, "Array.prototype.pop");
 
-  var array = TO_OBJECT_INLINE(this);
+  var array = TO_OBJECT(this);
   var n = TO_UINT32(array.length);
   if (n == 0) {
     array.length = n;
@@ -512,7 +512,7 @@ function ArrayPush() {
   if (%IsObserved(this))
     return ObservedArrayPush.apply(this, arguments);
 
-  var array = TO_OBJECT_INLINE(this);
+  var array = TO_OBJECT(this);
   var n = TO_UINT32(array.length);
   var m = %_ArgumentsLength();
 
@@ -532,7 +532,7 @@ function ArrayPush() {
 function ArrayConcatJS(arg1) {  // length == 1
   CHECK_OBJECT_COERCIBLE(this, "Array.prototype.concat");
 
-  var array = $toObject(this);
+  var array = TO_OBJECT(this);
   var arg_count = %_ArgumentsLength();
   var arrays = new InternalArray(1 + arg_count);
   arrays[0] = array;
@@ -627,7 +627,7 @@ function GenericArrayReverse(array, len) {
 function ArrayReverse() {
   CHECK_OBJECT_COERCIBLE(this, "Array.prototype.reverse");
 
-  var array = TO_OBJECT_INLINE(this);
+  var array = TO_OBJECT(this);
   var len = TO_UINT32(array.length);
   var isArray = IS_ARRAY(array);
 
@@ -662,7 +662,7 @@ function ObservedArrayShift(len) {
 function ArrayShift() {
   CHECK_OBJECT_COERCIBLE(this, "Array.prototype.shift");
 
-  var array = TO_OBJECT_INLINE(this);
+  var array = TO_OBJECT(this);
   var len = TO_UINT32(array.length);
 
   if (len === 0) {
@@ -716,7 +716,7 @@ function ArrayUnshift(arg1) {  // length == 1
   if (%IsObserved(this))
     return ObservedArrayUnshift.apply(this, arguments);
 
-  var array = TO_OBJECT_INLINE(this);
+  var array = TO_OBJECT(this);
   var len = TO_UINT32(array.length);
   var num_arguments = %_ArgumentsLength();
 
@@ -740,7 +740,7 @@ function ArrayUnshift(arg1) {  // length == 1
 function ArraySlice(start, end) {
   CHECK_OBJECT_COERCIBLE(this, "Array.prototype.slice");
 
-  var array = TO_OBJECT_INLINE(this);
+  var array = TO_OBJECT(this);
   var len = TO_UINT32(array.length);
   var start_i = TO_INTEGER(start);
   var end_i = len;
@@ -858,7 +858,7 @@ function ArraySplice(start, delete_count) {
     return ObservedArraySplice.apply(this, arguments);
 
   var num_arguments = %_ArgumentsLength();
-  var array = TO_OBJECT_INLINE(this);
+  var array = TO_OBJECT(this);
   var len = TO_UINT32(array.length);
   var start_i = ComputeSpliceStartIndex(TO_INTEGER(start), len);
   var del_count = ComputeSpliceDeleteCount(delete_count, num_arguments, len,
@@ -1190,7 +1190,7 @@ function InnerArraySort(length, comparefn) {
 function ArraySort(comparefn) {
   CHECK_OBJECT_COERCIBLE(this, "Array.prototype.sort");
 
-  var array = $toObject(this);
+  var array = TO_OBJECT(this);
   var length = TO_UINT32(array.length);
   return %_CallFunction(array, length, comparefn, InnerArraySort);
 }
@@ -1217,7 +1217,7 @@ function InnerArrayFilter(f, receiver, array, length) {
       var element = array[i];
       // Prepare break slots for debugger step in.
       if (stepping) %DebugPrepareStepInIfStepping(f);
-      var new_receiver = needs_wrapper ? $toObject(receiver) : receiver;
+      var new_receiver = needs_wrapper ? TO_OBJECT(receiver) : receiver;
       if (%_CallFunction(new_receiver, element, i, array, f)) {
         accumulator[accumulator_length++] = element;
       }
@@ -1231,7 +1231,7 @@ function ArrayFilter(f, receiver) {
 
   // Pull out the length so that modifications to the length in the
   // loop will not affect the looping and side effects are visible.
-  var array = $toObject(this);
+  var array = TO_OBJECT(this);
   var length = $toUint32(array.length);
   var accumulator = InnerArrayFilter(f, receiver, array, length);
   var result = new GlobalArray();
@@ -1255,7 +1255,7 @@ function InnerArrayForEach(f, receiver, array, length) {
       var element = array[i];
       // Prepare break slots for debugger step in.
       if (stepping) %DebugPrepareStepInIfStepping(f);
-      var new_receiver = needs_wrapper ? $toObject(receiver) : receiver;
+      var new_receiver = needs_wrapper ? TO_OBJECT(receiver) : receiver;
       %_CallFunction(new_receiver, element, i, array, f);
     }
   }
@@ -1266,7 +1266,7 @@ function ArrayForEach(f, receiver) {
 
   // Pull out the length so that modifications to the length in the
   // loop will not affect the looping and side effects are visible.
-  var array = $toObject(this);
+  var array = TO_OBJECT(this);
   var length = TO_UINT32(array.length);
   InnerArrayForEach(f, receiver, array, length);
 }
@@ -1288,7 +1288,7 @@ function InnerArraySome(f, receiver, array, length) {
       var element = array[i];
       // Prepare break slots for debugger step in.
       if (stepping) %DebugPrepareStepInIfStepping(f);
-      var new_receiver = needs_wrapper ? $toObject(receiver) : receiver;
+      var new_receiver = needs_wrapper ? TO_OBJECT(receiver) : receiver;
       if (%_CallFunction(new_receiver, element, i, array, f)) return true;
     }
   }
@@ -1303,7 +1303,7 @@ function ArraySome(f, receiver) {
 
   // Pull out the length so that modifications to the length in the
   // loop will not affect the looping and side effects are visible.
-  var array = $toObject(this);
+  var array = TO_OBJECT(this);
   var length = TO_UINT32(array.length);
   return InnerArraySome(f, receiver, array, length);
 }
@@ -1325,7 +1325,7 @@ function InnerArrayEvery(f, receiver, array, length) {
       var element = array[i];
       // Prepare break slots for debugger step in.
       if (stepping) %DebugPrepareStepInIfStepping(f);
-      var new_receiver = needs_wrapper ? $toObject(receiver) : receiver;
+      var new_receiver = needs_wrapper ? TO_OBJECT(receiver) : receiver;
       if (!%_CallFunction(new_receiver, element, i, array, f)) return false;
     }
   }
@@ -1337,7 +1337,7 @@ function ArrayEvery(f, receiver) {
 
   // Pull out the length so that modifications to the length in the
   // loop will not affect the looping and side effects are visible.
-  var array = $toObject(this);
+  var array = TO_OBJECT(this);
   var length = TO_UINT32(array.length);
   return InnerArrayEvery(f, receiver, array, length);
 }
@@ -1360,7 +1360,7 @@ function InnerArrayMap(f, receiver, array, length) {
       var element = array[i];
       // Prepare break slots for debugger step in.
       if (stepping) %DebugPrepareStepInIfStepping(f);
-      var new_receiver = needs_wrapper ? $toObject(receiver) : receiver;
+      var new_receiver = needs_wrapper ? TO_OBJECT(receiver) : receiver;
       accumulator[i] = %_CallFunction(new_receiver, element, i, array, f);
     }
   }
@@ -1373,7 +1373,7 @@ function ArrayMap(f, receiver) {
 
   // Pull out the length so that modifications to the length in the
   // loop will not affect the looping and side effects are visible.
-  var array = $toObject(this);
+  var array = TO_OBJECT(this);
   var length = TO_UINT32(array.length);
   var accumulator = InnerArrayMap(f, receiver, array, length);
   var result = new GlobalArray();
@@ -1542,7 +1542,7 @@ function ArrayReduce(callback, current) {
 
   // Pull out the length so that modifications to the length in the
   // loop will not affect the looping and side effects are visible.
-  var array = $toObject(this);
+  var array = TO_OBJECT(this);
   var length = $toUint32(array.length);
   return InnerArrayReduce(callback, current, array, length,
                           %_ArgumentsLength());
@@ -1585,7 +1585,7 @@ function ArrayReduceRight(callback, current) {
 
   // Pull out the length so that side effects are visible before the
   // callback function is checked.
-  var array = $toObject(this);
+  var array = TO_OBJECT(this);
   var length = $toUint32(array.length);
   return InnerArrayReduceRight(callback, current, array, length,
                                %_ArgumentsLength());
index 5f2f9d3..8385100 100644 (file)
@@ -1724,7 +1724,6 @@ void Genesis::InstallNativeFunctions() {
   INSTALL_NATIVE(JSFunction, "$toNumber", to_number_fun);
   INSTALL_NATIVE(JSFunction, "$toString", to_string_fun);
   INSTALL_NATIVE(JSFunction, "$toDetailString", to_detail_string_fun);
-  INSTALL_NATIVE(JSFunction, "$toObject", to_object_fun);
   INSTALL_NATIVE(JSFunction, "$toInteger", to_integer_fun);
   INSTALL_NATIVE(JSFunction, "$toUint32", to_uint32_fun);
   INSTALL_NATIVE(JSFunction, "$toInt32", to_int32_fun);
index d7cd720..212ad89 100644 (file)
@@ -182,7 +182,6 @@ enum BuiltinExtraArguments {
   V(CALL_NON_FUNCTION_AS_CONSTRUCTOR, 0)   \
   V(CALL_FUNCTION_PROXY, 1)                \
   V(CALL_FUNCTION_PROXY_AS_CONSTRUCTOR, 1) \
-  V(TO_OBJECT, 0)                          \
   V(TO_NUMBER, 0)                          \
   V(TO_STRING, 0)                          \
   V(TO_NAME, 0)                            \
index be34549..acbf515 100644 (file)
@@ -178,6 +178,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) {
   StringAddStub stub(isolate, flags, pretenure_flag);
index f750ab6..1386f05 100644 (file)
@@ -73,6 +73,7 @@ class CodeFactory final {
       ToBooleanStub::Types types = ToBooleanStub::Types());
 
   static Callable ToNumber(Isolate* isolate);
+  static Callable ToObject(Isolate* isolate);
 
   static Callable StringAdd(Isolate* isolate, StringAddFlags flags,
                             PretenureFlag pretenure_flag);
index fb46633..4afd592 100644 (file)
@@ -1657,6 +1657,16 @@ Handle<Code> ElementsTransitionAndStoreStub::GenerateCode() {
 }
 
 
+template <>
+HValue* CodeStubGraphBuilder<ToObjectStub>::BuildCodeStub() {
+  HValue* receiver = GetParameter(ToObjectDescriptor::kReceiverIndex);
+  return BuildToObject(receiver);
+}
+
+
+Handle<Code> ToObjectStub::GenerateCode() { return DoGenerateCode(this); }
+
+
 void CodeStubGraphBuilderBase::BuildCheckAndInstallOptimizedCode(
     HValue* js_function,
     HValue* native_context,
index ee57db7..cc77389 100644 (file)
@@ -672,6 +672,11 @@ void ElementsTransitionAndStoreStub::InitializeDescriptor(
 }
 
 
+void ToObjectStub::InitializeDescriptor(CodeStubDescriptor* descriptor) {
+  descriptor->Initialize(Runtime::FunctionForId(Runtime::kToObject)->entry);
+}
+
+
 CallInterfaceDescriptor StoreTransitionStub::GetCallInterfaceDescriptor()
     const {
   return StoreTransitionDescriptor(isolate());
index 372b788..f1759ee 100644 (file)
@@ -54,6 +54,7 @@ namespace internal {
   V(StubFailureTrampoline)                  \
   V(SubString)                              \
   V(ToNumber)                               \
+  V(ToObject)                               \
   V(VectorStoreICTrampoline)                \
   V(VectorKeyedStoreICTrampoline)           \
   V(VectorStoreIC)                          \
@@ -3050,6 +3051,15 @@ class ToNumberStub final : public PlatformCodeStub {
 };
 
 
+class ToObjectStub final : public HydrogenCodeStub {
+ public:
+  explicit ToObjectStub(Isolate* isolate) : HydrogenCodeStub(isolate) {}
+
+  DEFINE_CALL_INTERFACE_DESCRIPTOR(ToObject);
+  DEFINE_HYDROGEN_CODE_STUB(ToObject, HydrogenCodeStub);
+};
+
+
 class StringCompareStub : public PlatformCodeStub {
  public:
   explicit StringCompareStub(Isolate* isolate) : PlatformCodeStub(isolate) {}
index ceab164..f0bc423 100644 (file)
@@ -268,7 +268,7 @@ function SetForEach(f, receiver) {
   while (%SetIteratorNext(iterator, value_array)) {
     if (stepping) %DebugPrepareStepInIfStepping(f);
     key = value_array[0];
-    var new_receiver = needs_wrapper ? $toObject(receiver) : receiver;
+    var new_receiver = needs_wrapper ? TO_OBJECT(receiver) : receiver;
     %_CallFunction(new_receiver, key, key, this, f);
   }
 }
@@ -457,7 +457,7 @@ function MapForEach(f, receiver) {
   var value_array = [UNDEFINED, UNDEFINED];
   while (%MapIteratorNext(iterator, value_array)) {
     if (stepping) %DebugPrepareStepInIfStepping(f);
-    var new_receiver = needs_wrapper ? $toObject(receiver) : receiver;
+    var new_receiver = needs_wrapper ? TO_OBJECT(receiver) : receiver;
     %_CallFunction(new_receiver, value_array[1], value_array[0], this, f);
   }
 }
index a9861fc..0219aac 100644 (file)
@@ -307,7 +307,9 @@ void JSGenericLowering::LowerJSToName(Node* node) {
 
 
 void JSGenericLowering::LowerJSToObject(Node* node) {
-  ReplaceWithBuiltinCall(node, Builtins::TO_OBJECT, 1);
+  CallDescriptor::Flags flags = AdjustFrameStatesForCall(node);
+  Callable callable = CodeFactory::ToObject(isolate());
+  ReplaceWithStubCall(node, callable, flags);
 }
 
 
index 06ade91..e82ac20 100644 (file)
@@ -94,6 +94,8 @@ Reduction JSIntrinsicLowering::Reduce(Node* node) {
       return ReduceGetTypeFeedbackVector(node);
     case Runtime::kInlineGetCallerJSFunction:
       return ReduceGetCallerJSFunction(node);
+    case Runtime::kInlineToObject:
+      return ReduceToObject(node);
     case Runtime::kInlineThrowNotDateError:
       return ReduceThrowNotDateError(node);
     case Runtime::kInlineCallFunction:
@@ -528,6 +530,12 @@ Reduction JSIntrinsicLowering::ReduceThrowNotDateError(Node* node) {
 }
 
 
+Reduction JSIntrinsicLowering::ReduceToObject(Node* node) {
+  node->set_op(javascript()->ToObject());
+  return Changed(node);
+}
+
+
 Reduction JSIntrinsicLowering::ReduceCallFunction(Node* node) {
   CallRuntimeParameters params = OpParameter<CallRuntimeParameters>(node->op());
   size_t arity = params.arity();
index 816defb..c14882c 100644 (file)
@@ -58,6 +58,7 @@ class JSIntrinsicLowering final : public AdvancedReducer {
   Reduction ReduceGetTypeFeedbackVector(Node* node);
   Reduction ReduceGetCallerJSFunction(Node* node);
   Reduction ReduceThrowNotDateError(Node* node);
+  Reduction ReduceToObject(Node* node);
   Reduction ReduceCallFunction(Node* node);
 
   Reduction Change(Node* node, const Operator* op);
index c604909..51b29e3 100644 (file)
@@ -219,6 +219,7 @@ int Linkage::FrameStateInputCount(Runtime::FunctionId function) {
     case Runtime::kInlineGetCallerJSFunction:
     case Runtime::kInlineGetPrototype:
     case Runtime::kInlineRegExpExec:
+    case Runtime::kInlineToObject:
       return 1;
     case Runtime::kInlineDeoptimizeNow:
     case Runtime::kInlineThrowNotDateError:
index 85b73c8..aabcf4b 100644 (file)
@@ -1559,6 +1559,8 @@ Bounds Typer::Visitor::TypeJSCallRuntime(Node* node) {
       return Bounds(Type::None(), Type::Range(0, 32, zone()));
     case Runtime::kInlineStringGetLength:
       return Bounds(Type::None(), Type::Range(0, String::kMaxLength, zone()));
+    case Runtime::kInlineToObject:
+      return Bounds(Type::None(), Type::Receiver());
     default:
       break;
   }
index 37fc315..8e8f0b3 100644 (file)
@@ -97,7 +97,6 @@ enum BindingFlags {
   V(TO_NUMBER_FUN_INDEX, JSFunction, to_number_fun)                            \
   V(TO_STRING_FUN_INDEX, JSFunction, to_string_fun)                            \
   V(TO_DETAIL_STRING_FUN_INDEX, JSFunction, to_detail_string_fun)              \
-  V(TO_OBJECT_FUN_INDEX, JSFunction, to_object_fun)                            \
   V(TO_INTEGER_FUN_INDEX, JSFunction, to_integer_fun)                          \
   V(TO_UINT32_FUN_INDEX, JSFunction, to_uint32_fun)                            \
   V(TO_INT32_FUN_INDEX, JSFunction, to_int32_fun)                              \
@@ -363,7 +362,6 @@ class Context: public FixedArray {
     TO_NUMBER_FUN_INDEX,
     TO_STRING_FUN_INDEX,
     TO_DETAIL_STRING_FUN_INDEX,
-    TO_OBJECT_FUN_INDEX,
     TO_INTEGER_FUN_INDEX,
     TO_UINT32_FUN_INDEX,
     TO_INT32_FUN_INDEX,
index 118c8a6..56a72f0 100644 (file)
@@ -775,7 +775,7 @@ function DateToISOString() {
 
 
 function DateToJSON(key) {
-  var o = $toObject(this);
+  var o = TO_OBJECT(this);
   var tv = $defaultNumber(o);
   if (IS_NUMBER(tv) && !NUMBER_IS_FINITE(tv)) {
     return null;
index ab76d41..854f08b 100644 (file)
@@ -385,7 +385,8 @@ class OptimizedFunctionVisitor BASE_EMBEDDED {
   V(kValueMismatch, "value mismatch")                                          \
   V(kWrongInstanceType, "wrong instance type")                                 \
   V(kWrongMap, "wrong map")                                                    \
-  V(kUndefinedOrNullInForIn, "null or undefined in for-in")
+  V(kUndefinedOrNullInForIn, "null or undefined in for-in")                    \
+  V(kUndefinedOrNullInToObject, "null or undefined in ToObject")
 
 
 class Deoptimizer : public Malloced {
index cdfa787..687c0f9 100644 (file)
@@ -548,14 +548,6 @@ MaybeHandle<Object> Execution::ToDetailString(
 }
 
 
-MaybeHandle<Object> Execution::ToObject(
-    Isolate* isolate, Handle<Object> obj) {
-  if (obj->IsSpecObject()) return obj;
-  // TODO(verwaest): Use Object::ToObject but throw an exception on failure.
-  RETURN_NATIVE_CALL(to_object, { obj });
-}
-
-
 MaybeHandle<Object> Execution::ToInteger(
     Isolate* isolate, Handle<Object> obj) {
   RETURN_NATIVE_CALL(to_integer, { obj });
@@ -589,6 +581,16 @@ MaybeHandle<Object> Execution::NewDate(Isolate* isolate, double time) {
 #undef RETURN_NATIVE_CALL
 
 
+MaybeHandle<Object> Execution::ToObject(Isolate* isolate, Handle<Object> obj) {
+  Handle<JSReceiver> receiver;
+  if (JSReceiver::ToObject(isolate, obj).ToHandle(&receiver)) {
+    return receiver;
+  }
+  THROW_NEW_ERROR(
+      isolate, NewTypeError(MessageTemplate::kUndefinedOrNullToObject), Object);
+}
+
+
 MaybeHandle<JSRegExp> Execution::NewJSRegExp(Handle<String> pattern,
                                              Handle<String> flags) {
   Isolate* isolate = pattern->GetIsolate();
index a4d017e..c07438a 100644 (file)
@@ -1083,8 +1083,8 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
   __ CompareObjectType(r0, r1, r1, FIRST_SPEC_OBJECT_TYPE);
   __ b(ge, &done_convert);
   __ bind(&convert);
-  __ push(r0);
-  __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
+  ToObjectStub stub(isolate());
+  __ CallStub(&stub);
   __ bind(&done_convert);
   PrepareForBailoutForId(stmt->ToObjectId(), TOS_REG);
   __ push(r0);
@@ -4018,6 +4018,19 @@ void FullCodeGenerator::EmitNumberToString(CallRuntime* expr) {
 }
 
 
+void FullCodeGenerator::EmitToObject(CallRuntime* expr) {
+  ZoneList<Expression*>* args = expr->arguments();
+  DCHECK_EQ(1, args->length());
+
+  // Load the argument into r0 and convert it.
+  VisitForAccumulatorValue(args->at(0));
+
+  ToObjectStub stub(isolate());
+  __ CallStub(&stub);
+  context()->Plug(r0);
+}
+
+
 void FullCodeGenerator::EmitStringCharFromCode(CallRuntime* expr) {
   ZoneList<Expression*>* args = expr->arguments();
   DCHECK(args->length() == 1);
index 205af1e..99cf863 100644 (file)
@@ -1085,8 +1085,8 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
   __ JumpIfSmi(x0, &convert);
   __ JumpIfObjectType(x0, x10, x11, FIRST_SPEC_OBJECT_TYPE, &done_convert, ge);
   __ Bind(&convert);
-  __ Push(x0);
-  __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
+  ToObjectStub stub(isolate());
+  __ CallStub(&stub);
   __ Bind(&done_convert);
   PrepareForBailoutForId(stmt->ToObjectId(), TOS_REG);
   __ Push(x0);
@@ -3726,6 +3726,19 @@ void FullCodeGenerator::EmitNumberToString(CallRuntime* expr) {
 }
 
 
+void FullCodeGenerator::EmitToObject(CallRuntime* expr) {
+  ZoneList<Expression*>* args = expr->arguments();
+  DCHECK_EQ(1, args->length());
+
+  // Load the argument into x0 and convert it.
+  VisitForAccumulatorValue(args->at(0));
+
+  ToObjectStub stub(isolate());
+  __ CallStub(&stub);
+  context()->Plug(x0);
+}
+
+
 void FullCodeGenerator::EmitStringCharFromCode(CallRuntime* expr) {
   ZoneList<Expression*>* args = expr->arguments();
   DCHECK(args->length() == 1);
index f90925d..d83712a 100644 (file)
@@ -531,6 +531,7 @@ class FullCodeGenerator: public AstVisitor {
   F(RegExpConstructResult)                \
   F(GetFromCache)                         \
   F(NumberToString)                       \
+  F(ToObject)                             \
   F(DebugIsActive)
 
 #define GENERATOR_DECLARATION(Name) void Emit##Name(CallRuntime* call);
index 93f11cc..0d814d6 100644 (file)
@@ -1025,8 +1025,8 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
   __ CmpObjectType(eax, FIRST_SPEC_OBJECT_TYPE, ecx);
   __ j(above_equal, &done_convert, Label::kNear);
   __ bind(&convert);
-  __ push(eax);
-  __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
+  ToObjectStub stub(isolate());
+  __ CallStub(&stub);
   __ bind(&done_convert);
   PrepareForBailoutForId(stmt->ToObjectId(), TOS_REG);
   __ push(eax);
@@ -3921,6 +3921,19 @@ void FullCodeGenerator::EmitNumberToString(CallRuntime* expr) {
 }
 
 
+void FullCodeGenerator::EmitToObject(CallRuntime* expr) {
+  ZoneList<Expression*>* args = expr->arguments();
+  DCHECK_EQ(1, args->length());
+
+  // Load the argument into eax and convert it.
+  VisitForAccumulatorValue(args->at(0));
+
+  ToObjectStub stub(isolate());
+  __ CallStub(&stub);
+  context()->Plug(eax);
+}
+
+
 void FullCodeGenerator::EmitStringCharFromCode(CallRuntime* expr) {
   ZoneList<Expression*>* args = expr->arguments();
   DCHECK(args->length() == 1);
index 62bc935..9e033e2 100644 (file)
@@ -1085,8 +1085,8 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
   __ GetObjectType(a0, a1, a1);
   __ Branch(&done_convert, ge, a1, Operand(FIRST_SPEC_OBJECT_TYPE));
   __ bind(&convert);
-  __ push(a0);
-  __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
+  ToObjectStub stub(isolate());
+  __ CallStub(&stub);
   __ mov(a0, v0);
   __ bind(&done_convert);
   PrepareForBailoutForId(stmt->ToObjectId(), TOS_REG);
@@ -4028,6 +4028,20 @@ void FullCodeGenerator::EmitNumberToString(CallRuntime* expr) {
 }
 
 
+void FullCodeGenerator::EmitToObject(CallRuntime* expr) {
+  ZoneList<Expression*>* args = expr->arguments();
+  DCHECK_EQ(1, args->length());
+
+  // Load the argument into a0 and convert it.
+  VisitForAccumulatorValue(args->at(0));
+  __ mov(a0, result_register());
+
+  ToObjectStub stub(isolate());
+  __ CallStub(&stub);
+  context()->Plug(v0);
+}
+
+
 void FullCodeGenerator::EmitStringCharFromCode(CallRuntime* expr) {
   ZoneList<Expression*>* args = expr->arguments();
   DCHECK(args->length() == 1);
index 21426b7..a1d8950 100644 (file)
@@ -1082,8 +1082,8 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
   __ GetObjectType(a0, a1, a1);
   __ Branch(&done_convert, ge, a1, Operand(FIRST_SPEC_OBJECT_TYPE));
   __ bind(&convert);
-  __ push(a0);
-  __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
+  ToObjectStub stub(isolate());
+  __ CallStub(&stub);
   __ mov(a0, v0);
   __ bind(&done_convert);
   PrepareForBailoutForId(stmt->ToObjectId(), TOS_REG);
@@ -4031,6 +4031,20 @@ void FullCodeGenerator::EmitNumberToString(CallRuntime* expr) {
 }
 
 
+void FullCodeGenerator::EmitToObject(CallRuntime* expr) {
+  ZoneList<Expression*>* args = expr->arguments();
+  DCHECK_EQ(1, args->length());
+
+  // Load the argument into a0 and convert it.
+  VisitForAccumulatorValue(args->at(0));
+  __ mov(a0, result_register());
+
+  ToObjectStub stub(isolate());
+  __ CallStub(&stub);
+  context()->Plug(v0);
+}
+
+
 void FullCodeGenerator::EmitStringCharFromCode(CallRuntime* expr) {
   ZoneList<Expression*>* args = expr->arguments();
   DCHECK(args->length() == 1);
index 7a754df..7234e6a 100644 (file)
@@ -1046,8 +1046,8 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
   __ CompareObjectType(r3, r4, r4, FIRST_SPEC_OBJECT_TYPE);
   __ bge(&done_convert);
   __ bind(&convert);
-  __ push(r3);
-  __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
+  ToObjectStub stub(isolate());
+  __ CallStub(&stub);
   __ bind(&done_convert);
   PrepareForBailoutForId(stmt->ToObjectId(), TOS_REG);
   __ push(r3);
@@ -4029,6 +4029,18 @@ void FullCodeGenerator::EmitNumberToString(CallRuntime* expr) {
 }
 
 
+void FullCodeGenerator::EmitToObject(CallRuntime* expr) {
+  ZoneList<Expression*>* args = expr->arguments();
+  DCHECK_EQ(1, args->length());
+  // Load the argument into r3 and convert it.
+  VisitForAccumulatorValue(args->at(0));
+
+  ToObjectStub stub(isolate());
+  __ CallStub(&stub);
+  context()->Plug(r3);
+}
+
+
 void FullCodeGenerator::EmitStringCharFromCode(CallRuntime* expr) {
   ZoneList<Expression*>* args = expr->arguments();
   DCHECK(args->length() == 1);
index d8c60ad..377bf67 100644 (file)
@@ -1039,12 +1039,12 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
 
   // Convert the object to a JS object.
   Label convert, done_convert;
-  __ JumpIfSmi(rax, &convert);
+  __ JumpIfSmi(rax, &convert, Label::kNear);
   __ CmpObjectType(rax, FIRST_SPEC_OBJECT_TYPE, rcx);
-  __ j(above_equal, &done_convert);
+  __ j(above_equal, &done_convert, Label::kNear);
   __ bind(&convert);
-  __ Push(rax);
-  __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
+  ToObjectStub stub(isolate());
+  __ CallStub(&stub);
   __ bind(&done_convert);
   PrepareForBailoutForId(stmt->ToObjectId(), TOS_REG);
   __ Push(rax);
@@ -3912,6 +3912,19 @@ void FullCodeGenerator::EmitNumberToString(CallRuntime* expr) {
 }
 
 
+void FullCodeGenerator::EmitToObject(CallRuntime* expr) {
+  ZoneList<Expression*>* args = expr->arguments();
+  DCHECK_EQ(1, args->length());
+
+  // Load the argument into rax and convert it.
+  VisitForAccumulatorValue(args->at(0));
+
+  ToObjectStub stub(isolate());
+  __ CallStub(&stub);
+  context()->Plug(rax);
+}
+
+
 void FullCodeGenerator::EmitStringCharFromCode(CallRuntime* expr) {
   ZoneList<Expression*>* args = expr->arguments();
   DCHECK(args->length() == 1);
index d4ef701..dbe28ae 100644 (file)
@@ -1018,8 +1018,8 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
   __ CmpObjectType(eax, FIRST_SPEC_OBJECT_TYPE, ecx);
   __ j(above_equal, &done_convert, Label::kNear);
   __ bind(&convert);
-  __ push(eax);
-  __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
+  ToObjectStub stub(isolate());
+  __ CallStub(&stub);
   __ bind(&done_convert);
   PrepareForBailoutForId(stmt->ToObjectId(), TOS_REG);
   __ push(eax);
@@ -3912,6 +3912,19 @@ void FullCodeGenerator::EmitNumberToString(CallRuntime* expr) {
 }
 
 
+void FullCodeGenerator::EmitToObject(CallRuntime* expr) {
+  ZoneList<Expression*>* args = expr->arguments();
+  DCHECK_EQ(1, args->length());
+
+  // Load the argument into eax and convert it.
+  VisitForAccumulatorValue(args->at(0));
+
+  ToObjectStub stub(isolate());
+  __ CallStub(&stub);
+  context()->Plug(eax);
+}
+
+
 void FullCodeGenerator::EmitStringCharFromCode(CallRuntime* expr) {
   ZoneList<Expression*>* args = expr->arguments();
   DCHECK(args->length() == 1);
index b133f1e..8710d9a 100644 (file)
@@ -16,7 +16,7 @@ var GlobalArray = global.Array;
 // https://github.com/tc39/Array.prototype.includes
 // 6e3b78c927aeda20b9d40e81303f9d44596cd904
 function ArrayIncludes(searchElement, fromIndex) {
-  var array = $toObject(this);
+  var array = TO_OBJECT(this);
   var len = $toLength(array.length);
 
   if (len === 0) {
index e94134b..709a6e9 100644 (file)
@@ -83,7 +83,7 @@ function InnerArrayCopyWithin(target, start, end, array, length) {
 function ArrayCopyWithin(target, start, end) {
   CHECK_OBJECT_COERCIBLE(this, "Array.prototype.copyWithin");
 
-  var array = TO_OBJECT_INLINE(this);
+  var array = TO_OBJECT(this);
   var length = $toLength(array.length);
 
   return InnerArrayCopyWithin(target, start, end, array, length);
@@ -103,7 +103,7 @@ function InnerArrayFind(predicate, thisArg, array, length) {
 
   for (var i = 0; i < length; i++) {
     var element = array[i];
-    var newThisArg = needs_wrapper ? $toObject(thisArg) : thisArg;
+    var newThisArg = needs_wrapper ? TO_OBJECT(thisArg) : thisArg;
     if (%_CallFunction(newThisArg, element, i, array, predicate)) {
       return element;
     }
@@ -116,7 +116,7 @@ function InnerArrayFind(predicate, thisArg, array, length) {
 function ArrayFind(predicate, thisArg) {
   CHECK_OBJECT_COERCIBLE(this, "Array.prototype.find");
 
-  var array = $toObject(this);
+  var array = TO_OBJECT(this);
   var length = $toInteger(array.length);
 
   return InnerArrayFind(predicate, thisArg, array, length);
@@ -136,7 +136,7 @@ function InnerArrayFindIndex(predicate, thisArg, array, length) {
 
   for (var i = 0; i < length; i++) {
     var element = array[i];
-    var newThisArg = needs_wrapper ? $toObject(thisArg) : thisArg;
+    var newThisArg = needs_wrapper ? TO_OBJECT(thisArg) : thisArg;
     if (%_CallFunction(newThisArg, element, i, array, predicate)) {
       return i;
     }
@@ -149,7 +149,7 @@ function InnerArrayFindIndex(predicate, thisArg, array, length) {
 function ArrayFindIndex(predicate, thisArg) {
   CHECK_OBJECT_COERCIBLE(this, "Array.prototype.findIndex");
 
-  var array = $toObject(this);
+  var array = TO_OBJECT(this);
   var length = $toInteger(array.length);
 
   return InnerArrayFindIndex(predicate, thisArg, array, length);
@@ -187,7 +187,7 @@ function InnerArrayFill(value, start, end, array, length) {
 function ArrayFill(value, start, end) {
   CHECK_OBJECT_COERCIBLE(this, "Array.prototype.fill");
 
-  var array = $toObject(this);
+  var array = TO_OBJECT(this);
   var length = TO_UINT32(array.length);
 
   return InnerArrayFill(value, start, end, array, length);
@@ -205,7 +205,7 @@ function AddArrayElement(constructor, array, i, value) {
 
 // ES6, draft 10-14-14, section 22.1.2.1
 function ArrayFrom(arrayLike, mapfn, receiver) {
-  var items = $toObject(arrayLike);
+  var items = TO_OBJECT(arrayLike);
   var mapping = !IS_UNDEFINED(mapfn);
 
   if (mapping) {
@@ -215,7 +215,7 @@ function ArrayFrom(arrayLike, mapfn, receiver) {
       if (IS_NULL(receiver)) {
         receiver = UNDEFINED;
       } else if (!IS_UNDEFINED(receiver)) {
-        receiver = TO_OBJECT_INLINE(receiver);
+        receiver = TO_OBJECT(receiver);
       }
     }
   }
index 382f7f4..e0555ba 100644 (file)
@@ -24,7 +24,7 @@ utils.Import(function(from) {
 
 // ES6, draft 04-03-15, section 19.1.2.1
 function ObjectAssign(target, sources) {
-  var to = TO_OBJECT_INLINE(target);
+  var to = TO_OBJECT(target);
   var argsLen = %_ArgumentsLength();
   if (argsLen < 2) return to;
 
@@ -34,7 +34,7 @@ function ObjectAssign(target, sources) {
       continue;
     }
 
-    var from = TO_OBJECT_INLINE(nextSource);
+    var from = TO_OBJECT(nextSource);
     var keys = OwnPropertyKeys(from);
     var len = keys.length;
 
index 8054691..4e8c16d 100644 (file)
@@ -2032,6 +2032,165 @@ HValue* HGraphBuilder::BuildNumberToString(HValue* object, Type* type) {
 }
 
 
+HValue* HGraphBuilder::BuildToObject(HValue* receiver) {
+  NoObservableSideEffectsScope scope(this);
+
+  // Create a joinable continuation.
+  HIfContinuation wrap(graph()->CreateBasicBlock(),
+                       graph()->CreateBasicBlock());
+
+  // Determine the proper global constructor function required to wrap
+  // {receiver} into a JSValue, unless {receiver} is already a {JSReceiver}, in
+  // which case we just return it.  Deopts to Runtime::kToObject if {receiver}
+  // is undefined or null.
+  IfBuilder receiver_is_smi(this);
+  receiver_is_smi.If<HIsSmiAndBranch>(receiver);
+  receiver_is_smi.Then();
+  {
+    // Load native context.
+    HValue* native_context = BuildGetNativeContext();
+
+    // Load global Number function.
+    HValue* constructor = Add<HLoadNamedField>(
+        native_context, nullptr,
+        HObjectAccess::ForContextSlot(Context::NUMBER_FUNCTION_INDEX));
+    Push(constructor);
+  }
+  receiver_is_smi.Else();
+  {
+    // Determine {receiver} map and instance type.
+    HValue* receiver_map =
+        Add<HLoadNamedField>(receiver, nullptr, HObjectAccess::ForMap());
+    HValue* receiver_instance_type = Add<HLoadNamedField>(
+        receiver_map, nullptr, HObjectAccess::ForMapInstanceType());
+
+    // First check whether {receiver} is already a spec object (fast case).
+    IfBuilder receiver_is_not_spec_object(this);
+    receiver_is_not_spec_object.If<HCompareNumericAndBranch>(
+        receiver_instance_type, Add<HConstant>(FIRST_SPEC_OBJECT_TYPE),
+        Token::LT);
+    receiver_is_not_spec_object.Then();
+    {
+      // Load native context.
+      HValue* native_context = BuildGetNativeContext();
+
+      IfBuilder receiver_is_heap_number(this);
+      receiver_is_heap_number.If<HCompareNumericAndBranch>(
+          receiver_instance_type, Add<HConstant>(HEAP_NUMBER_TYPE), Token::EQ);
+      receiver_is_heap_number.Then();
+      {
+        // Load global Number function.
+        HValue* constructor = Add<HLoadNamedField>(
+            native_context, nullptr,
+            HObjectAccess::ForContextSlot(Context::NUMBER_FUNCTION_INDEX));
+        Push(constructor);
+      }
+      receiver_is_heap_number.Else();
+      {
+        // Load boolean map (we cannot decide based on instance type, because
+        // it's ODDBALL_TYPE, which would also include null and undefined).
+        HValue* boolean_map = Add<HLoadRoot>(Heap::kBooleanMapRootIndex);
+
+        IfBuilder receiver_is_boolean(this);
+        receiver_is_boolean.If<HCompareObjectEqAndBranch>(receiver_map,
+                                                          boolean_map);
+        receiver_is_boolean.Then();
+        {
+          // Load global Boolean function.
+          HValue* constructor = Add<HLoadNamedField>(
+              native_context, nullptr,
+              HObjectAccess::ForContextSlot(Context::BOOLEAN_FUNCTION_INDEX));
+          Push(constructor);
+        }
+        receiver_is_boolean.Else();
+        {
+          IfBuilder receiver_is_string(this);
+          receiver_is_string.If<HCompareNumericAndBranch>(
+              receiver_instance_type, Add<HConstant>(FIRST_NONSTRING_TYPE),
+              Token::LT);
+          receiver_is_string.Then();
+          {
+            // Load global String function.
+            HValue* constructor = Add<HLoadNamedField>(
+                native_context, nullptr,
+                HObjectAccess::ForContextSlot(Context::STRING_FUNCTION_INDEX));
+            Push(constructor);
+          }
+          receiver_is_string.Else();
+          {
+            IfBuilder receiver_is_symbol(this);
+            receiver_is_symbol.If<HCompareNumericAndBranch>(
+                receiver_instance_type, Add<HConstant>(SYMBOL_TYPE), Token::EQ);
+            receiver_is_symbol.Then();
+            {
+              // Load global Symbol function.
+              HValue* constructor = Add<HLoadNamedField>(
+                  native_context, nullptr, HObjectAccess::ForContextSlot(
+                                               Context::SYMBOL_FUNCTION_INDEX));
+              Push(constructor);
+            }
+            receiver_is_symbol.Else();
+            {
+              IfBuilder receiver_is_float32x4(this);
+              receiver_is_float32x4.If<HCompareNumericAndBranch>(
+                  receiver_instance_type, Add<HConstant>(FLOAT32X4_TYPE),
+                  Token::EQ);
+              receiver_is_float32x4.Then();
+              {
+                // Load global Float32x4 function.
+                HValue* constructor = Add<HLoadNamedField>(
+                    native_context, nullptr,
+                    HObjectAccess::ForContextSlot(
+                        Context::FLOAT32X4_FUNCTION_INDEX));
+                Push(constructor);
+              }
+              receiver_is_float32x4.ElseDeopt(
+                  Deoptimizer::kUndefinedOrNullInToObject);
+              receiver_is_float32x4.JoinContinuation(&wrap);
+            }
+            receiver_is_symbol.JoinContinuation(&wrap);
+          }
+          receiver_is_string.JoinContinuation(&wrap);
+        }
+        receiver_is_boolean.JoinContinuation(&wrap);
+      }
+      receiver_is_heap_number.JoinContinuation(&wrap);
+    }
+    receiver_is_not_spec_object.JoinContinuation(&wrap);
+  }
+  receiver_is_smi.JoinContinuation(&wrap);
+
+  // Wrap the receiver if necessary.
+  IfBuilder if_wrap(this, &wrap);
+  if_wrap.Then();
+  {
+    // Determine the initial map for the global constructor.
+    HValue* constructor = Pop();
+    HValue* constructor_initial_map = Add<HLoadNamedField>(
+        constructor, nullptr, HObjectAccess::ForPrototypeOrInitialMap());
+    // Allocate and initialize a JSValue wrapper.
+    HValue* value =
+        BuildAllocate(Add<HConstant>(JSValue::kSize), HType::JSObject(),
+                      JS_VALUE_TYPE, HAllocationMode());
+    Add<HStoreNamedField>(value, HObjectAccess::ForMap(),
+                          constructor_initial_map);
+    HValue* empty_fixed_array = Add<HLoadRoot>(Heap::kEmptyFixedArrayRootIndex);
+    Add<HStoreNamedField>(value, HObjectAccess::ForPropertiesPointer(),
+                          empty_fixed_array);
+    Add<HStoreNamedField>(value, HObjectAccess::ForElementsPointer(),
+                          empty_fixed_array);
+    Add<HStoreNamedField>(value, HObjectAccess::ForObservableJSObjectOffset(
+                                     JSValue::kValueOffset),
+                          receiver);
+    Push(value);
+  }
+  if_wrap.Else();
+  { Push(receiver); }
+  if_wrap.End();
+  return Pop();
+}
+
+
 HAllocate* HGraphBuilder::BuildAllocate(
     HValue* object_size,
     HType type,
index ea74caf..cc6ddaa 100644 (file)
@@ -1329,6 +1329,7 @@ class HGraphBuilder {
                                    bool is_jsarray);
 
   HValue* BuildNumberToString(HValue* object, Type* type);
+  HValue* BuildToObject(HValue* receiver);
 
   void BuildJSObjectCheck(HValue* receiver,
                           int bit_field_mask);
index 6b6d4af..1028bbb 100644 (file)
@@ -251,7 +251,7 @@ function supportedLocalesOf(service, locales, options) {
   if (IS_UNDEFINED(options)) {
     options = {};
   } else {
-    options = $toObject(options);
+    options = TO_OBJECT(options);
   }
 
   var matcher = options.localeMatcher;
@@ -717,7 +717,7 @@ function initializeLocaleList(locales) {
       return freezeArray(seen);
     }
 
-    var o = $toObject(locales);
+    var o = TO_OBJECT(locales);
     var len = TO_UINT32(o.length);
 
     for (var k = 0; k < len; k++) {
@@ -951,7 +951,7 @@ function initializeCollator(collator, locales, options) {
       return new Intl.Collator(locales, options);
     }
 
-    return initializeCollator($toObject(this), locales, options);
+    return initializeCollator(TO_OBJECT(this), locales, options);
   },
   DONT_ENUM
 );
@@ -1192,7 +1192,7 @@ function initializeNumberFormat(numberFormat, locales, options) {
       return new Intl.NumberFormat(locales, options);
     }
 
-    return initializeNumberFormat($toObject(this), locales, options);
+    return initializeNumberFormat(TO_OBJECT(this), locales, options);
   },
   DONT_ENUM
 );
@@ -1444,7 +1444,7 @@ function toDateTimeOptions(options, required, defaults) {
   if (IS_UNDEFINED(options)) {
     options = {};
   } else {
-    options = TO_OBJECT_INLINE(options);
+    options = TO_OBJECT(options);
   }
 
   var needsDefault = true;
@@ -1594,7 +1594,7 @@ function initializeDateTimeFormat(dateFormat, locales, options) {
       return new Intl.DateTimeFormat(locales, options);
     }
 
-    return initializeDateTimeFormat($toObject(this), locales, options);
+    return initializeDateTimeFormat(TO_OBJECT(this), locales, options);
   },
   DONT_ENUM
 );
@@ -1814,7 +1814,7 @@ function initializeBreakIterator(iterator, locales, options) {
       return new Intl.v8BreakIterator(locales, options);
     }
 
-    return initializeBreakIterator($toObject(this), locales, options);
+    return initializeBreakIterator(TO_OBJECT(this), locales, options);
   },
   DONT_ENUM
 );
index 5e42f84..c4509e2 100644 (file)
@@ -994,8 +994,9 @@ void Builtins::Generate_FunctionCall(MacroAssembler* masm) {
       __ SmiTag(eax);
       __ push(eax);
 
-      __ push(ebx);
-      __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
+      __ mov(eax, ebx);
+      ToObjectStub stub(masm->isolate());
+      __ CallStub(&stub);
       __ mov(ebx, eax);
       __ Move(edx, Immediate(0));  // restore
 
@@ -1215,8 +1216,9 @@ static void Generate_ApplyHelper(MacroAssembler* masm, bool targetIsArgument) {
     __ j(above_equal, &push_receiver);
 
     __ bind(&call_to_object);
-    __ push(ebx);
-    __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
+    __ mov(eax, ebx);
+    ToObjectStub stub(masm->isolate());
+    __ CallStub(&stub);
     __ mov(ebx, eax);
     __ jmp(&push_receiver);
 
index 525edea..bf2630b 100644 (file)
@@ -2093,8 +2093,8 @@ static void EmitWrapCase(MacroAssembler* masm, int argc, Label* cont) {
   // Wrap the receiver and patch it back onto the stack.
   { FrameScope frame_scope(masm, StackFrame::INTERNAL);
     __ push(edi);
-    __ push(eax);
-    __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
+    ToObjectStub stub(masm->isolate());
+    __ CallStub(&stub);
     __ pop(edi);
   }
   __ mov(Operand(esp, (argc + 1) * kPointerSize), eax);
index 61508ee..496b34e 100644 (file)
@@ -103,6 +103,10 @@ void ToNumberDescriptor::InitializePlatformSpecific(
 }
 
 
+// static
+const Register ToObjectDescriptor::ReceiverRegister() { return eax; }
+
+
 void NumberToStringDescriptor::InitializePlatformSpecific(
     CallInterfaceDescriptorData* data) {
   Register registers[] = {eax};
index 89ee975..da9eb29 100644 (file)
@@ -155,6 +155,13 @@ void InstanceofDescriptor::InitializePlatformSpecific(
 }
 
 
+void ToObjectDescriptor::InitializePlatformSpecific(
+    CallInterfaceDescriptorData* data) {
+  Register registers[] = {ReceiverRegister()};
+  data->InitializePlatformSpecific(arraysize(registers), registers);
+}
+
+
 void MathPowTaggedDescriptor::InitializePlatformSpecific(
     CallInterfaceDescriptorData* data) {
   Register registers[] = {exponent()};
index c5e104f..a016797 100644 (file)
@@ -24,6 +24,7 @@ class PlatformInterfaceDescriptor;
   V(FastNewClosure)                           \
   V(FastNewContext)                           \
   V(ToNumber)                                 \
+  V(ToObject)                                 \
   V(NumberToString)                           \
   V(Typeof)                                   \
   V(FastCloneShallowArray)                    \
@@ -339,6 +340,16 @@ class ToNumberDescriptor : public CallInterfaceDescriptor {
 };
 
 
+class ToObjectDescriptor : public CallInterfaceDescriptor {
+ public:
+  enum ParameterIndices { kReceiverIndex };
+
+  DECLARE_DESCRIPTOR(ToObjectDescriptor, CallInterfaceDescriptor)
+
+  static const Register ReceiverRegister();
+};
+
+
 class NumberToStringDescriptor : public CallInterfaceDescriptor {
  public:
   DECLARE_DESCRIPTOR(NumberToStringDescriptor, CallInterfaceDescriptor)
index 91b4132..de5fe8b 100644 (file)
@@ -154,7 +154,7 @@ macro TO_INT32(arg) = (%_IsSmi(%IS_VAR(arg)) ? arg : (arg >> 0));
 macro TO_UINT32(arg) = (arg >>> 0);
 macro TO_STRING_INLINE(arg) = (IS_STRING(%IS_VAR(arg)) ? arg : $nonStringToString(arg));
 macro TO_NUMBER_INLINE(arg) = (IS_NUMBER(%IS_VAR(arg)) ? arg : $nonNumberToNumber(arg));
-macro TO_OBJECT_INLINE(arg) = (IS_SPEC_OBJECT(%IS_VAR(arg)) ? arg : $toObject(arg));
+macro TO_OBJECT(arg) = (%_ToObject(arg));
 macro JSON_NUMBER_TO_STRING(arg) = ((%_IsSmi(%IS_VAR(arg)) || arg - arg == 0) ? %_NumberToString(arg) : "null");
 macro HAS_OWN_PROPERTY(arg, index) = (%_CallFunction(arg, index, ObjectHasOwnProperty));
 macro SHOULD_CREATE_WRAPPER(functionName, receiver) = (!IS_SPEC_OBJECT(receiver) && %IsSloppyModeFunction(functionName));
index 63cefc8..3829eda 100644 (file)
@@ -67,7 +67,7 @@ var GlobalEvalError;
 function NoSideEffectsObjectToString() {
   if (IS_UNDEFINED(this) && !IS_UNDETECTABLE(this)) return "[object Undefined]";
   if (IS_NULL(this)) return "[object Null]";
-  return "[object " + %_ClassOf(TO_OBJECT_INLINE(this)) + "]";
+  return "[object " + %_ClassOf(TO_OBJECT(this)) + "]";
 }
 
 
index 711277d..ec3e059 100644 (file)
@@ -1313,8 +1313,10 @@ void Builtins::Generate_FunctionCall(MacroAssembler* masm) {
     {
       FrameScope scope(masm, StackFrame::INTERNAL);
       __ sll(a0, a0, kSmiTagSize);  // Smi tagged.
-      __ Push(a0, a2);
-      __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
+      __ push(a0);
+      __ mov(a0, a2);
+      ToObjectStub stub(masm->isolate());
+      __ CallStub(&stub);
       __ mov(a2, v0);
 
       __ pop(a0);
@@ -1548,8 +1550,8 @@ static void Generate_ApplyHelper(MacroAssembler* masm, bool targetIsArgument) {
     // Convert the receiver to a regular object.
     // a0: receiver
     __ bind(&call_to_object);
-    __ push(a0);
-    __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
+    ToObjectStub stub(masm->isolate());
+    __ CallStub(&stub);
     __ mov(a0, v0);  // Put object in a0 to match other paths to push_receiver.
     __ Branch(&push_receiver);
 
index 5ebb70e..daff32f 100644 (file)
@@ -2675,8 +2675,10 @@ static void EmitSlowCase(MacroAssembler* masm,
 static void EmitWrapCase(MacroAssembler* masm, int argc, Label* cont) {
   // Wrap the receiver and patch it back onto the stack.
   { FrameScope frame_scope(masm, StackFrame::INTERNAL);
-    __ Push(a1, a3);
-    __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
+    __ Push(a1);
+    __ mov(a0, a3);
+    ToObjectStub stub(masm->isolate());
+    __ CallStub(&stub);
     __ pop(a1);
   }
   __ Branch(USE_DELAY_SLOT, cont);
index f0618ad..df36520 100644 (file)
@@ -95,6 +95,10 @@ void ToNumberDescriptor::InitializePlatformSpecific(
 }
 
 
+// static
+const Register ToObjectDescriptor::ReceiverRegister() { return a0; }
+
+
 void NumberToStringDescriptor::InitializePlatformSpecific(
     CallInterfaceDescriptorData* data) {
   Register registers[] = {a0};
index 0888939..3fb288b 100644 (file)
@@ -1309,8 +1309,10 @@ void Builtins::Generate_FunctionCall(MacroAssembler* masm) {
     {
       FrameScope scope(masm, StackFrame::INTERNAL);
       __ SmiTag(a0);
-      __ Push(a0, a2);
-      __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
+      __ Push(a0);
+      __ mov(a0, a2);
+      ToObjectStub stub(masm->isolate());
+      __ CallStub(&stub);
       __ mov(a2, v0);
 
       __ pop(a0);
@@ -1545,8 +1547,8 @@ static void Generate_ApplyHelper(MacroAssembler* masm, bool targetIsArgument) {
     // Convert the receiver to a regular object.
     // a0: receiver
     __ bind(&call_to_object);
-    __ push(a0);
-    __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
+    ToObjectStub stub(masm->isolate());
+    __ CallStub(&stub);
     __ mov(a0, v0);  // Put object in a0 to match other paths to push_receiver.
     __ Branch(&push_receiver);
 
index 494d947..8b46e4c 100644 (file)
@@ -2714,8 +2714,10 @@ static void EmitSlowCase(MacroAssembler* masm,
 static void EmitWrapCase(MacroAssembler* masm, int argc, Label* cont) {
   // Wrap the receiver and patch it back onto the stack.
   { FrameScope frame_scope(masm, StackFrame::INTERNAL);
-    __ Push(a1, a3);
-    __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
+    __ Push(a1);
+    __ mov(a0, a3);
+    ToObjectStub stub(masm->isolate());
+    __ CallStub(&stub);
     __ pop(a1);
   }
   __ Branch(USE_DELAY_SLOT, cont);
index 87c8ffb..1498d92 100644 (file)
@@ -95,6 +95,10 @@ void ToNumberDescriptor::InitializePlatformSpecific(
 }
 
 
+// static
+const Register ToObjectDescriptor::ReceiverRegister() { return a0; }
+
+
 void NumberToStringDescriptor::InitializePlatformSpecific(
     CallInterfaceDescriptorData* data) {
   Register registers[] = {a0};
index bdcf406..4dc06fe 100644 (file)
@@ -1338,8 +1338,10 @@ void Builtins::Generate_FunctionCall(MacroAssembler* masm) {
       // Enter an internal frame in order to preserve argument count.
       FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL);
       __ SmiTag(r3);
-      __ Push(r3, r5);
-      __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
+      __ Push(r3);
+      __ mr(r3, r5);
+      ToObjectStub stub(masm->isolate());
+      __ CallStub(&stub);
       __ mr(r5, r3);
 
       __ pop(r3);
@@ -1592,8 +1594,8 @@ static void Generate_ApplyHelper(MacroAssembler* masm, bool targetIsArgument) {
     // Convert the receiver to a regular object.
     // r3: receiver
     __ bind(&call_to_object);
-    __ push(r3);
-    __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
+    ToObjectStub stub(masm->isolate());
+    __ CallStub(&stub);
     __ b(&push_receiver);
 
     __ bind(&use_global_proxy);
index 015a6ef..59aa8b1 100644 (file)
@@ -2726,8 +2726,10 @@ static void EmitWrapCase(MacroAssembler* masm, int argc, Label* cont) {
   // Wrap the receiver and patch it back onto the stack.
   {
     FrameAndConstantPoolScope frame_scope(masm, StackFrame::INTERNAL);
-    __ Push(r4, r6);
-    __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
+    __ push(r4);
+    __ mr(r3, r6);
+    ToObjectStub stub(masm->isolate());
+    __ CallStub(&stub);
     __ pop(r4);
   }
   __ StoreP(r3, MemOperand(sp, argc * kPointerSize), r0);
index c59fc56..8b60511 100644 (file)
@@ -95,6 +95,10 @@ void ToNumberDescriptor::InitializePlatformSpecific(
 }
 
 
+// static
+const Register ToObjectDescriptor::ReceiverRegister() { return r3; }
+
+
 void NumberToStringDescriptor::InitializePlatformSpecific(
     CallInterfaceDescriptorData* data) {
   Register registers[] = {r3};
index 63a733f..000d497 100644 (file)
@@ -58,7 +58,6 @@ var APPLY_PREPARE;
 var REFLECT_APPLY_PREPARE;
 var REFLECT_CONSTRUCT_PREPARE;
 var STACK_OVERFLOW;
-var TO_OBJECT;
 var TO_NUMBER;
 var TO_STRING;
 var TO_NAME;
@@ -76,7 +75,6 @@ var $toInteger;
 var $toLength;
 var $toName;
 var $toNumber;
-var $toObject;
 var $toPositiveInteger;
 var $toPrimitive;
 var $toString;
@@ -512,7 +510,7 @@ SHR_STRONG = function SHR_STRONG(y) {
 
 // ECMA-262, section 11.4.1, page 46.
 DELETE = function DELETE(key, language_mode) {
-  return %DeleteProperty(%$toObject(this), key, language_mode);
+  return %DeleteProperty(TO_OBJECT(this), key, language_mode);
 }
 
 
@@ -730,12 +728,6 @@ STACK_OVERFLOW = function STACK_OVERFLOW(length) {
 }
 
 
-// Convert the receiver to an object - forward to ToObject.
-TO_OBJECT = function TO_OBJECT() {
-  return %$toObject(this);
-}
-
-
 // Convert the receiver to a number - forward to ToNumber.
 TO_NUMBER = function TO_NUMBER() {
   return %$toNumber(this);
@@ -832,20 +824,6 @@ function ToName(x) {
 }
 
 
-// ECMA-262, section 9.9, page 36.
-function ToObject(x) {
-  if (IS_STRING(x)) return new GlobalString(x);
-  if (IS_NUMBER(x)) return new GlobalNumber(x);
-  if (IS_BOOLEAN(x)) return new GlobalBoolean(x);
-  if (IS_SYMBOL(x)) return %NewSymbolWrapper(x);
-  if (IS_FLOAT32X4(x)) return %NewFloat32x4Wrapper(x);
-  if (IS_NULL_OR_UNDEFINED(x) && !IS_UNDETECTABLE(x)) {
-    throw MakeTypeError(kUndefinedOrNullToObject);
-  }
-  return x;
-}
-
-
 // ECMA-262, section 9.4, page 34.
 function ToInteger(x) {
   if (%_IsSmi(x)) return x;
@@ -1006,7 +984,6 @@ $toInteger = ToInteger;
 $toLength = ToLength;
 $toName = ToName;
 $toNumber = ToNumber;
-$toObject = ToObject;
 $toPositiveInteger = ToPositiveInteger;
 $toPrimitive = ToPrimitive;
 $toString = ToString;
index 255dbf0..04f15be 100644 (file)
@@ -1461,5 +1461,19 @@ RUNTIME_FUNCTION(Runtime_DefineSetterPropertyUnchecked) {
                                setter, attrs));
   return isolate->heap()->undefined_value();
 }
+
+
+RUNTIME_FUNCTION(Runtime_ToObject) {
+  HandleScope scope(isolate);
+  DCHECK_EQ(1, args.length());
+  CONVERT_ARG_HANDLE_CHECKED(Object, object, 0);
+  Handle<JSReceiver> receiver;
+  if (JSReceiver::ToObject(isolate, object).ToHandle(&receiver)) {
+    return *receiver;
+  }
+  THROW_NEW_ERROR_RETURN_FAILURE(
+      isolate, NewTypeError(MessageTemplate::kUndefinedOrNullToObject));
+}
+
 }  // namespace internal
 }  // namespace v8
index 5c60ad5..12c3171 100644 (file)
         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)        \
@@ -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
index 412ee0a..bd4f3ed 100644 (file)
@@ -51,14 +51,6 @@ RUNTIME_FUNCTION(Runtime_CreateGlobalPrivateSymbol) {
 }
 
 
-RUNTIME_FUNCTION(Runtime_NewSymbolWrapper) {
-  HandleScope scope(isolate);
-  DCHECK(args.length() == 1);
-  CONVERT_ARG_HANDLE_CHECKED(Symbol, symbol, 0);
-  return *Object::ToObject(isolate, symbol).ToHandleChecked();
-}
-
-
 RUNTIME_FUNCTION(Runtime_SymbolDescription) {
   SealHandleScope shs(isolate);
   DCHECK(args.length() == 1);
index 6d7c8cc..f89618d 100644 (file)
@@ -497,7 +497,8 @@ namespace internal {
   F(IsStrong, 1, 1)                                  \
   F(ClassOf, 1, 1)                                   \
   F(DefineGetterPropertyUnchecked, 4, 1)             \
-  F(DefineSetterPropertyUnchecked, 4, 1)
+  F(DefineSetterPropertyUnchecked, 4, 1)             \
+  F(ToObject, 1, 1)
 
 
 #define FOR_EACH_INTRINSIC_OBSERVE(F)            \
@@ -570,7 +571,6 @@ namespace internal {
 
 #define FOR_EACH_INTRINSIC_SIMD(F) \
   F(CreateFloat32x4, 4, 1)         \
-  F(NewFloat32x4Wrapper, 1, 1)     \
   F(Float32x4Check, 1, 1)          \
   F(Float32x4ExtractLane, 2, 1)    \
   F(Float32x4Equals, 2, 1)         \
@@ -620,7 +620,6 @@ namespace internal {
   F(CreateSymbol, 1, 1)              \
   F(CreatePrivateSymbol, 1, 1)       \
   F(CreateGlobalPrivateSymbol, 1, 1) \
-  F(NewSymbolWrapper, 1, 1)          \
   F(SymbolDescription, 1, 1)         \
   F(SymbolRegistry, 0, 1)            \
   F(SymbolIsPrivate, 1, 1)
index 536430e..bb392ef 100644 (file)
@@ -41,7 +41,7 @@ function CreateStringIterator(string) {
 
 // 21.1.5.2.1 %StringIteratorPrototype%.next( )
 function StringIteratorNext() {
-  var iterator = $toObject(this);
+  var iterator = TO_OBJECT(this);
 
   if (!HAS_DEFINED_PRIVATE(iterator, stringIteratorNextIndexSymbol)) {
     throw MakeTypeError(kIncompatibleMethodReceiver,
index 387e5be..322e5ae 100644 (file)
@@ -1112,8 +1112,8 @@ function StringFromCodePoint(_) {  // length = 1
 function StringRaw(callSite) {
   // TODO(caitp): Use rest parameters when implemented
   var numberOfSubstitutions = %_ArgumentsLength();
-  var cooked = $toObject(callSite);
-  var raw = $toObject(cooked.raw);
+  var cooked = TO_OBJECT(callSite);
+  var raw = TO_OBJECT(cooked.raw);
   var literalSegments = $toLength(raw.length);
   if (literalSegments <= 0) return "";
 
index 8ac7fe7..5c5ec00 100644 (file)
@@ -78,7 +78,7 @@ function SymbolKeyFor(symbol) {
 
 // ES6 19.1.2.8
 function ObjectGetOwnPropertySymbols(obj) {
-  obj = $toObject(obj);
+  obj = TO_OBJECT(obj);
 
   // TODO(arv): Proxies use a shared trap for String and Symbol keys.
 
index 92769e2..542d709 100644 (file)
@@ -141,7 +141,7 @@ utils.InstallFunctions(global, DONT_ENUM, [
 function ObjectToString() {
   if (IS_UNDEFINED(this) && !IS_UNDETECTABLE(this)) return "[object Undefined]";
   if (IS_NULL(this)) return "[object Null]";
-  var O = TO_OBJECT_INLINE(this);
+  var O = TO_OBJECT(this);
   var builtinTag = %_ClassOf(O);
   var tag;
 
@@ -168,14 +168,14 @@ function ObjectToLocaleString() {
 
 // ECMA-262 - 15.2.4.4
 function ObjectValueOf() {
-  return TO_OBJECT_INLINE(this);
+  return TO_OBJECT(this);
 }
 
 
 // ECMA-262 - 15.2.4.5
 function ObjectHasOwnProperty(value) {
   var name = $toName(value);
-  var object = TO_OBJECT_INLINE(this);
+  var object = TO_OBJECT(this);
 
   if (%_IsJSProxy(object)) {
     // TODO(rossberg): adjust once there is a story for symbols vs proxies.
@@ -206,7 +206,7 @@ function ObjectPropertyIsEnumerable(V) {
     var desc = GetOwnPropertyJS(this, P);
     return IS_UNDEFINED(desc) ? false : desc.isEnumerable();
   }
-  return %IsPropertyEnumerable(TO_OBJECT_INLINE(this), P);
+  return %IsPropertyEnumerable(TO_OBJECT(this), P);
 }
 
 
@@ -223,7 +223,7 @@ function ObjectDefineGetter(name, fun) {
   desc.setGet(fun);
   desc.setEnumerable(true);
   desc.setConfigurable(true);
-  DefineOwnProperty(TO_OBJECT_INLINE(receiver), $toName(name), desc, false);
+  DefineOwnProperty(TO_OBJECT(receiver), $toName(name), desc, false);
 }
 
 
@@ -232,7 +232,7 @@ function ObjectLookupGetter(name) {
   if (receiver == null && !IS_UNDETECTABLE(receiver)) {
     receiver = %GlobalProxy(ObjectLookupGetter);
   }
-  return %LookupAccessor(TO_OBJECT_INLINE(receiver), $toName(name), GETTER);
+  return %LookupAccessor(TO_OBJECT(receiver), $toName(name), GETTER);
 }
 
 
@@ -248,7 +248,7 @@ function ObjectDefineSetter(name, fun) {
   desc.setSet(fun);
   desc.setEnumerable(true);
   desc.setConfigurable(true);
-  DefineOwnProperty(TO_OBJECT_INLINE(receiver), $toName(name), desc, false);
+  DefineOwnProperty(TO_OBJECT(receiver), $toName(name), desc, false);
 }
 
 
@@ -257,12 +257,12 @@ function ObjectLookupSetter(name) {
   if (receiver == null && !IS_UNDETECTABLE(receiver)) {
     receiver = %GlobalProxy(ObjectLookupSetter);
   }
-  return %LookupAccessor(TO_OBJECT_INLINE(receiver), $toName(name), SETTER);
+  return %LookupAccessor(TO_OBJECT(receiver), $toName(name), SETTER);
 }
 
 
 function ObjectKeys(obj) {
-  obj = TO_OBJECT_INLINE(obj);
+  obj = TO_OBJECT(obj);
   if (%_IsJSProxy(obj)) {
     var handler = %GetHandler(obj);
     var names = CallTrap0(handler, "keys", ProxyDerivedKeysTrap);
@@ -579,7 +579,7 @@ function GetOwnPropertyJS(obj, v) {
   // GetOwnProperty returns an array indexed by the constants
   // defined in macros.py.
   // If p is not a property on obj undefined is returned.
-  var props = %GetOwnProperty(TO_OBJECT_INLINE(obj), p);
+  var props = %GetOwnProperty(TO_OBJECT(obj), p);
 
   return ConvertDescriptorArrayToDescriptor(props);
 }
@@ -868,7 +868,7 @@ function DefineOwnPropertyFromAPI(obj, p, value, desc) {
 
 // ES6 section 19.1.2.9
 function ObjectGetPrototypeOf(obj) {
-  return %_GetPrototype(TO_OBJECT_INLINE(obj));
+  return %_GetPrototype(TO_OBJECT(obj));
 }
 
 // ES6 section 19.1.2.19.
@@ -889,7 +889,7 @@ function ObjectSetPrototypeOf(obj, proto) {
 
 // ES6 section 19.1.2.6
 function ObjectGetOwnPropertyDescriptor(obj, p) {
-  var desc = GetOwnPropertyJS(TO_OBJECT_INLINE(obj), p);
+  var desc = GetOwnPropertyJS(TO_OBJECT(obj), p);
   return FromPropertyDescriptor(desc);
 }
 
@@ -1001,7 +1001,7 @@ function OwnPropertyKeys(obj) {
 
 // ES5 section 15.2.3.4.
 function ObjectGetOwnPropertyNames(obj) {
-  obj = TO_OBJECT_INLINE(obj);
+  obj = TO_OBJECT(obj);
   // Special handling for proxies.
   if (%_IsJSProxy(obj)) {
     var handler = %GetHandler(obj);
@@ -1093,7 +1093,7 @@ function ObjectDefineProperties(obj, properties) {
   if (!IS_SPEC_OBJECT(obj)) {
     throw MakeTypeError(kCalledOnNonObject, "Object.defineProperties");
   }
-  var props = TO_OBJECT_INLINE(properties);
+  var props = TO_OBJECT(properties);
   var names = GetOwnEnumerablePropertyNames(props);
   var descriptors = new InternalArray();
   for (var i = 0; i < names.length; i++) {
@@ -1263,7 +1263,7 @@ function ObjectIs(obj1, obj2) {
 
 // ECMA-262, Edition 6, section B.2.2.1.1
 function ObjectGetProto() {
-  return %_GetPrototype(TO_OBJECT_INLINE(this));
+  return %_GetPrototype(TO_OBJECT(this));
 }
 
 
@@ -1280,10 +1280,10 @@ function ObjectSetProto(proto) {
 function ObjectConstructor(x) {
   if (%_IsConstructCall()) {
     if (x == null) return this;
-    return TO_OBJECT_INLINE(x);
+    return TO_OBJECT(x);
   } else {
     if (x == null) return { };
-    return TO_OBJECT_INLINE(x);
+    return TO_OBJECT(x);
   }
 }
 
index 8e78215..c8b1321 100644 (file)
@@ -1053,8 +1053,9 @@ void Builtins::Generate_FunctionCall(MacroAssembler* masm) {
       __ Integer32ToSmi(rax, rax);
       __ Push(rax);
 
-      __ Push(rbx);
-      __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
+      __ movp(rax, rbx);
+      ToObjectStub stub(masm->isolate());
+      __ CallStub(&stub);
       __ movp(rbx, rax);
       __ Set(rdx, 0);  // indicate regular JS_FUNCTION
 
@@ -1274,8 +1275,9 @@ static void Generate_ApplyHelper(MacroAssembler* masm, bool targetIsArgument) {
 
     // Convert the receiver to an object.
     __ bind(&call_to_object);
-    __ Push(rbx);
-    __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
+    __ movp(rax, rbx);
+    ToObjectStub stub(masm->isolate());
+    __ CallStub(&stub);
     __ movp(rbx, rax);
     __ jmp(&push_receiver, Label::kNear);
 
index 7d71701..3ab60c8 100644 (file)
@@ -1964,8 +1964,8 @@ static void EmitWrapCase(MacroAssembler* masm,
   // Wrap the receiver and patch it back onto the stack.
   { FrameScope frame_scope(masm, StackFrame::INTERNAL);
     __ Push(rdi);
-    __ Push(rax);
-    __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
+    ToObjectStub stub(masm->isolate());
+    __ CallStub(&stub);
     __ Pop(rdi);
   }
   __ movp(args->GetReceiverOperand(), rax);
index da5e506..9fd4470 100644 (file)
@@ -103,6 +103,10 @@ void ToNumberDescriptor::InitializePlatformSpecific(
 }
 
 
+// static
+const Register ToObjectDescriptor::ReceiverRegister() { return rax; }
+
+
 void NumberToStringDescriptor::InitializePlatformSpecific(
     CallInterfaceDescriptorData* data) {
   Register registers[] = {rax};
index da427e2..f6cf7a1 100644 (file)
@@ -994,8 +994,9 @@ void Builtins::Generate_FunctionCall(MacroAssembler* masm) {
       __ SmiTag(eax);
       __ push(eax);
 
-      __ push(ebx);
-      __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
+      __ mov(eax, ebx);
+      ToObjectStub stub(masm->isolate());
+      __ CallStub(&stub);
       __ mov(ebx, eax);
       __ Move(edx, Immediate(0));  // restore
 
@@ -1215,8 +1216,9 @@ static void Generate_ApplyHelper(MacroAssembler* masm, bool targetIsArgument) {
     __ j(above_equal, &push_receiver);
 
     __ bind(&call_to_object);
-    __ push(ebx);
-    __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
+    __ mov(eax, ebx);
+    ToObjectStub stub(masm->isolate());
+    __ CallStub(&stub);
     __ mov(ebx, eax);
     __ jmp(&push_receiver);
 
index e70f9c8..cdcbaf9 100644 (file)
@@ -1800,8 +1800,8 @@ static void EmitWrapCase(MacroAssembler* masm, int argc, Label* cont) {
   // Wrap the receiver and patch it back onto the stack.
   { FrameScope frame_scope(masm, StackFrame::INTERNAL);
     __ push(edi);
-    __ push(eax);
-    __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
+    ToObjectStub stub(masm->isolate());
+    __ CallStub(&stub);
     __ pop(edi);
   }
   __ mov(Operand(esp, (argc + 1) * kPointerSize), eax);
index dacbf10..7e03fac 100644 (file)
@@ -103,6 +103,10 @@ void ToNumberDescriptor::InitializePlatformSpecific(
 }
 
 
+// static
+const Register ToObjectDescriptor::ReceiverRegister() { return eax; }
+
+
 void NumberToStringDescriptor::InitializePlatformSpecific(
     CallInterfaceDescriptorData* data) {
   Register registers[] = {eax};