| Index: src/code-stubs-hydrogen.cc
|
| diff --git a/src/code-stubs-hydrogen.cc b/src/code-stubs-hydrogen.cc
|
| index fb46633f0b3c961f20931053ea2a26d24263e885..c97e3686091647451b4a056d7c5821d0e1820146 100644
|
| --- a/src/code-stubs-hydrogen.cc
|
| +++ b/src/code-stubs-hydrogen.cc
|
| @@ -1657,6 +1657,156 @@ Handle<Code> ElementsTransitionAndStoreStub::GenerateCode() {
|
| }
|
|
|
|
|
| +template <>
|
| +HValue* CodeStubGraphBuilder<ToObjectStub>::BuildCodeStub() {
|
| + HValue* receiver = GetParameter(ToObjectDescriptor::kReceiverIndex);
|
| + // 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.End();
|
| + }
|
| + receiver_is_symbol.End();
|
| + }
|
| + receiver_is_string.End();
|
| + }
|
| + receiver_is_boolean.End();
|
| + }
|
| + receiver_is_heap_number.End();
|
| + }
|
| + receiver_is_not_spec_object.Else();
|
| + receiver_is_not_spec_object.Return(receiver);
|
| + receiver_is_not_spec_object.End();
|
| + }
|
| + receiver_is_smi.End();
|
| + // 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);
|
| + return value;
|
| +}
|
| +
|
| +
|
| +Handle<Code> ToObjectStub::GenerateCode() { return DoGenerateCode(this); }
|
| +
|
| +
|
| void CodeStubGraphBuilderBase::BuildCheckAndInstallOptimizedCode(
|
| HValue* js_function,
|
| HValue* native_context,
|
|
|