| Index: src/code-stubs-hydrogen.cc
|
| diff --git a/src/code-stubs-hydrogen.cc b/src/code-stubs-hydrogen.cc
|
| index 0d960dd6198d5b223aa42a524d236e0af5dd88bf..de63f15bba797ff2d51080451952e000a7c21ee3 100644
|
| --- a/src/code-stubs-hydrogen.cc
|
| +++ b/src/code-stubs-hydrogen.cc
|
| @@ -376,191 +376,6 @@ HValue* CodeStubGraphBuilderBase::BuildPushElement(HValue* object, HValue* argc,
|
| }
|
|
|
| template <>
|
| -HValue* CodeStubGraphBuilder<FastFunctionBindStub>::BuildCodeStub() {
|
| - // TODO(verwaest): Fix deoptimizer messages.
|
| - HValue* argc = GetArgumentsLength();
|
| - HInstruction* argument_elements = Add<HArgumentsElements>(false, false);
|
| - HInstruction* object = Add<HAccessArgumentsAt>(argument_elements, argc,
|
| - graph()->GetConstantMinus1());
|
| - BuildCheckHeapObject(object);
|
| - HValue* map = Add<HLoadNamedField>(object, nullptr, HObjectAccess::ForMap());
|
| - Add<HCheckInstanceType>(object, HCheckInstanceType::IS_JS_FUNCTION);
|
| -
|
| - // Disallow binding of slow-mode functions. We need to figure out whether the
|
| - // length and name property are in the original state.
|
| - {
|
| - HValue* bit_field3 =
|
| - Add<HLoadNamedField>(map, nullptr, HObjectAccess::ForMapBitField3());
|
| - HValue* mask = Add<HConstant>(static_cast<int>(Map::DictionaryMap::kMask));
|
| - HValue* bit = AddUncasted<HBitwise>(Token::BIT_AND, bit_field3, mask);
|
| - IfBuilder check(this);
|
| - check.If<HCompareNumericAndBranch>(bit, mask, Token::EQ);
|
| - check.ThenDeopt(DeoptimizeReason::kFastPathFailed);
|
| - check.End();
|
| - }
|
| -
|
| - // Check whether the length and name properties are still present as
|
| - // AccessorInfo objects. In that case, their value can be recomputed even if
|
| - // the actual value on the object changes.
|
| - {
|
| - HValue* descriptors =
|
| - Add<HLoadNamedField>(map, nullptr, HObjectAccess::ForMapDescriptors());
|
| -
|
| - HValue* descriptors_length = Add<HLoadNamedField>(
|
| - descriptors, nullptr, HObjectAccess::ForFixedArrayLength());
|
| - IfBuilder range(this);
|
| - range.If<HCompareNumericAndBranch>(descriptors_length,
|
| - graph()->GetConstant1(), Token::LTE);
|
| - range.ThenDeopt(DeoptimizeReason::kFastPathFailed);
|
| - range.End();
|
| -
|
| - // Verify .length.
|
| - const int length_index = JSFunction::kLengthDescriptorIndex;
|
| - HValue* maybe_length = Add<HLoadKeyed>(
|
| - descriptors, Add<HConstant>(DescriptorArray::ToKeyIndex(length_index)),
|
| - nullptr, nullptr, FAST_ELEMENTS);
|
| - Unique<Name> length_string = Unique<Name>::CreateUninitialized(
|
| - isolate()->factory()->length_string());
|
| - Add<HCheckValue>(maybe_length, length_string, false);
|
| -
|
| - HValue* maybe_length_accessor = Add<HLoadKeyed>(
|
| - descriptors,
|
| - Add<HConstant>(DescriptorArray::ToValueIndex(length_index)), nullptr,
|
| - nullptr, FAST_ELEMENTS);
|
| - BuildCheckHeapObject(maybe_length_accessor);
|
| - Add<HCheckMaps>(maybe_length_accessor,
|
| - isolate()->factory()->accessor_info_map());
|
| -
|
| - // Verify .name.
|
| - const int name_index = JSFunction::kNameDescriptorIndex;
|
| - HValue* maybe_name = Add<HLoadKeyed>(
|
| - descriptors, Add<HConstant>(DescriptorArray::ToKeyIndex(name_index)),
|
| - nullptr, nullptr, FAST_ELEMENTS);
|
| - Unique<Name> name_string =
|
| - Unique<Name>::CreateUninitialized(isolate()->factory()->name_string());
|
| - Add<HCheckValue>(maybe_name, name_string, false);
|
| -
|
| - HValue* maybe_name_accessor = Add<HLoadKeyed>(
|
| - descriptors, Add<HConstant>(DescriptorArray::ToValueIndex(name_index)),
|
| - nullptr, nullptr, FAST_ELEMENTS);
|
| - BuildCheckHeapObject(maybe_name_accessor);
|
| - Add<HCheckMaps>(maybe_name_accessor,
|
| - isolate()->factory()->accessor_info_map());
|
| - }
|
| -
|
| - // Choose the right bound function map based on whether the target is
|
| - // constructable.
|
| - {
|
| - HValue* bit_field =
|
| - Add<HLoadNamedField>(map, nullptr, HObjectAccess::ForMapBitField());
|
| - HValue* mask = Add<HConstant>(static_cast<int>(1 << Map::kIsConstructor));
|
| - HValue* bits = AddUncasted<HBitwise>(Token::BIT_AND, bit_field, mask);
|
| -
|
| - HValue* native_context = BuildGetNativeContext();
|
| - IfBuilder is_constructor(this);
|
| - is_constructor.If<HCompareNumericAndBranch>(bits, mask, Token::EQ);
|
| - is_constructor.Then();
|
| - {
|
| - HValue* map = Add<HLoadNamedField>(
|
| - native_context, nullptr,
|
| - HObjectAccess::ForContextSlot(
|
| - Context::BOUND_FUNCTION_WITH_CONSTRUCTOR_MAP_INDEX));
|
| - environment()->Push(map);
|
| - }
|
| - is_constructor.Else();
|
| - {
|
| - HValue* map = Add<HLoadNamedField>(
|
| - native_context, nullptr,
|
| - HObjectAccess::ForContextSlot(
|
| - Context::BOUND_FUNCTION_WITHOUT_CONSTRUCTOR_MAP_INDEX));
|
| - environment()->Push(map);
|
| - }
|
| - is_constructor.End();
|
| - }
|
| - HValue* bound_function_map = environment()->Pop();
|
| -
|
| - // Verify that __proto__ matches that of a the target bound function.
|
| - {
|
| - HValue* prototype =
|
| - Add<HLoadNamedField>(map, nullptr, HObjectAccess::ForPrototype());
|
| - HValue* expected_prototype = Add<HLoadNamedField>(
|
| - bound_function_map, nullptr, HObjectAccess::ForPrototype());
|
| - IfBuilder equal_prototype(this);
|
| - equal_prototype.IfNot<HCompareObjectEqAndBranch>(prototype,
|
| - expected_prototype);
|
| - equal_prototype.ThenDeopt(DeoptimizeReason::kFastPathFailed);
|
| - equal_prototype.End();
|
| - }
|
| -
|
| - // Allocate the arguments array.
|
| - IfBuilder empty_args(this);
|
| - empty_args.If<HCompareNumericAndBranch>(argc, graph()->GetConstant1(),
|
| - Token::LTE);
|
| - empty_args.Then();
|
| - { environment()->Push(Add<HLoadRoot>(Heap::kEmptyFixedArrayRootIndex)); }
|
| - empty_args.Else();
|
| - {
|
| - HValue* elements_length = AddUncasted<HSub>(argc, graph()->GetConstant1());
|
| - HValue* elements =
|
| - BuildAllocateAndInitializeArray(FAST_ELEMENTS, elements_length);
|
| -
|
| - LoopBuilder builder(this, context(), LoopBuilder::kPostIncrement);
|
| - HValue* start = graph()->GetConstant1();
|
| - HValue* key = builder.BeginBody(start, argc, Token::LT);
|
| - {
|
| - HValue* argument = Add<HAccessArgumentsAt>(argument_elements, argc, key);
|
| - HValue* index = AddUncasted<HSub>(key, graph()->GetConstant1());
|
| - AddElementAccess(elements, index, argument, elements, nullptr,
|
| - FAST_ELEMENTS, STORE);
|
| - }
|
| - builder.EndBody();
|
| - environment()->Push(elements);
|
| - }
|
| - empty_args.End();
|
| - HValue* elements = environment()->Pop();
|
| -
|
| - // Find the 'this' to bind.
|
| - IfBuilder no_receiver(this);
|
| - no_receiver.If<HCompareNumericAndBranch>(argc, graph()->GetConstant0(),
|
| - Token::EQ);
|
| - no_receiver.Then();
|
| - { environment()->Push(Add<HLoadRoot>(Heap::kUndefinedValueRootIndex)); }
|
| - no_receiver.Else();
|
| - {
|
| - environment()->Push(Add<HAccessArgumentsAt>(argument_elements, argc,
|
| - graph()->GetConstant0()));
|
| - }
|
| - no_receiver.End();
|
| - HValue* receiver = environment()->Pop();
|
| -
|
| - // Allocate the resulting bound function.
|
| - HValue* size = Add<HConstant>(JSBoundFunction::kSize);
|
| - HValue* bound_function =
|
| - Add<HAllocate>(size, HType::JSObject(), NOT_TENURED,
|
| - JS_BOUND_FUNCTION_TYPE, graph()->GetConstant0());
|
| - Add<HStoreNamedField>(bound_function, HObjectAccess::ForMap(),
|
| - bound_function_map);
|
| - HValue* empty_fixed_array = Add<HLoadRoot>(Heap::kEmptyFixedArrayRootIndex);
|
| - Add<HStoreNamedField>(bound_function, HObjectAccess::ForPropertiesPointer(),
|
| - empty_fixed_array);
|
| - Add<HStoreNamedField>(bound_function, HObjectAccess::ForElementsPointer(),
|
| - empty_fixed_array);
|
| - Add<HStoreNamedField>(bound_function, HObjectAccess::ForBoundTargetFunction(),
|
| - object);
|
| -
|
| - Add<HStoreNamedField>(bound_function, HObjectAccess::ForBoundThis(),
|
| - receiver);
|
| - Add<HStoreNamedField>(bound_function, HObjectAccess::ForBoundArguments(),
|
| - elements);
|
| -
|
| - return bound_function;
|
| -}
|
| -
|
| -Handle<Code> FastFunctionBindStub::GenerateCode() {
|
| - return DoGenerateCode(this);
|
| -}
|
| -
|
| -template <>
|
| HValue* CodeStubGraphBuilder<LoadFastElementStub>::BuildCodeStub() {
|
| LoadKeyedHoleMode hole_mode = casted_stub()->convert_hole_to_undefined()
|
| ? CONVERT_HOLE_TO_UNDEFINED
|
|
|