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 |