- // 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);
- }
- // TODO(bmeurer): Don't inline this into crankshaft code, as it will
- // deoptimize on all SIMD128 objects.
- receiver_is_symbol.ElseDeopt(
- Deoptimizer::kUndefinedOrNullInToObject);
- receiver_is_symbol.JoinContinuation(&wrap);
- }
- receiver_is_string.JoinContinuation(&wrap);
- }
- receiver_is_boolean.JoinContinuation(&wrap);
- }
- receiver_is_heap_number.JoinContinuation(&wrap);
+ // Load the constructor function index from the {receiver} map.
+ HValue* constructor_function_index = Add<HLoadNamedField>(
+ receiver_map, nullptr,
+ HObjectAccess::ForMapInObjectPropertiesOrConstructorFunctionIndex());
+
+ // Check if {receiver} has a constructor (null and undefined have no
+ // constructors, so we deoptimize to the runtime to throw an exception).
+ IfBuilder constructor_function_index_is_invalid(this);
+ constructor_function_index_is_invalid.If<HCompareNumericAndBranch>(
+ constructor_function_index,
+ Add<HConstant>(Map::kNoConstructorFunctionIndex), Token::EQ);
+ constructor_function_index_is_invalid.ThenDeopt(
+ Deoptimizer::kUndefinedOrNullInToObject);
+ constructor_function_index_is_invalid.End();
+
+ // Use the global constructor function.
+ Push(constructor_function_index);