| Index: src/compiler/js-native-context-specialization.cc
|
| diff --git a/src/compiler/js-native-context-specialization.cc b/src/compiler/js-native-context-specialization.cc
|
| index efe7cd623b27f9a5b6e1662b804d4cd6598adcae..fcf954e5c28aacb12593b8800b7486b755961ef8 100644
|
| --- a/src/compiler/js-native-context-specialization.cc
|
| +++ b/src/compiler/js-native-context-specialization.cc
|
| @@ -171,8 +171,7 @@ Reduction JSNativeContextSpecialization::ReduceNamedAccess(
|
| receiver, effect, control);
|
| } else {
|
| // Monomorphic property access.
|
| - receiver = effect = graph()->NewNode(simplified()->CheckHeapObject(),
|
| - receiver, effect, control);
|
| + receiver = BuildCheckHeapObject(receiver, &effect, control);
|
| effect = BuildCheckMaps(receiver, effect, control,
|
| access_info.receiver_maps());
|
| }
|
| @@ -210,8 +209,7 @@ Reduction JSNativeContextSpecialization::ReduceNamedAccess(
|
| receiverissmi_control = graph()->NewNode(common()->IfTrue(), branch);
|
| receiverissmi_effect = effect;
|
| } else {
|
| - receiver = effect = graph()->NewNode(simplified()->CheckHeapObject(),
|
| - receiver, effect, control);
|
| + receiver = BuildCheckHeapObject(receiver, &effect, control);
|
| }
|
|
|
| // Load the {receiver} map. The resulting effect is the dominating effect
|
| @@ -520,8 +518,7 @@ Reduction JSNativeContextSpecialization::ReduceElementAccess(
|
| }
|
|
|
| // Ensure that {receiver} is a heap object.
|
| - receiver = effect = graph()->NewNode(simplified()->CheckHeapObject(),
|
| - receiver, effect, control);
|
| + receiver = BuildCheckHeapObject(receiver, &effect, control);
|
|
|
| // Check for the monomorphic case.
|
| if (access_infos.size() == 1) {
|
| @@ -1070,8 +1067,7 @@ JSNativeContextSpecialization::BuildPropertyAccess(
|
| }
|
| case MachineRepresentation::kTaggedPointer: {
|
| // Ensure that {value} is a HeapObject.
|
| - value = effect = graph()->NewNode(simplified()->CheckHeapObject(),
|
| - value, effect, control);
|
| + value = BuildCheckHeapObject(value, &effect, control);
|
| Handle<Map> field_map;
|
| if (access_info.field_map().ToHandle(&field_map)) {
|
| // Emit a map check for the value.
|
| @@ -1165,34 +1161,61 @@ JSNativeContextSpecialization::BuildElementAccess(
|
| ElementsKind elements_kind = access_info.elements_kind();
|
| MapList const& receiver_maps = access_info.receiver_maps();
|
|
|
| - // Load the elements for the {receiver}.
|
| - Node* elements = effect = graph()->NewNode(
|
| - simplified()->LoadField(AccessBuilder::ForJSObjectElements()), receiver,
|
| - effect, control);
|
| -
|
| - // Don't try to store to a copy-on-write backing store.
|
| - if (access_mode == AccessMode::kStore &&
|
| - IsFastSmiOrObjectElementsKind(elements_kind) &&
|
| - store_mode != STORE_NO_TRANSITION_HANDLE_COW) {
|
| - effect =
|
| - graph()->NewNode(simplified()->CheckMaps(1), elements,
|
| - jsgraph()->FixedArrayMapConstant(), effect, control);
|
| - }
|
| -
|
| if (IsFixedTypedArrayElementsKind(elements_kind)) {
|
| - // Load the {receiver}s length.
|
| - Node* length = effect = graph()->NewNode(
|
| - simplified()->LoadField(AccessBuilder::ForJSTypedArrayLength()),
|
| - receiver, effect, control);
|
| + Node* buffer;
|
| + Node* length;
|
| + Node* base_pointer;
|
| + Node* external_pointer;
|
| +
|
| + // Check if we can constant-fold information about the {receiver} (i.e.
|
| + // for asm.js-like code patterns).
|
| + HeapObjectMatcher m(receiver);
|
| + if (m.HasValue() && m.Value()->IsJSTypedArray()) {
|
| + Handle<JSTypedArray> typed_array = Handle<JSTypedArray>::cast(m.Value());
|
| +
|
| + // Determine the {receiver}s (known) length.
|
| + length = jsgraph()->Constant(typed_array->length_value());
|
| +
|
| + // Check if the {receiver}s buffer was neutered.
|
| + buffer = jsgraph()->HeapConstant(typed_array->GetBuffer());
|
| +
|
| + // Load the (known) base and external pointer for the {receiver}. The
|
| + // {external_pointer} might be invalid if the {buffer} was neutered, so
|
| + // we need to make sure that any access is properly guarded.
|
| + base_pointer = jsgraph()->ZeroConstant();
|
| + external_pointer = jsgraph()->PointerConstant(
|
| + FixedTypedArrayBase::cast(typed_array->elements())
|
| + ->external_pointer());
|
| + } else {
|
| + // Load the {receiver}s length.
|
| + length = effect = graph()->NewNode(
|
| + simplified()->LoadField(AccessBuilder::ForJSTypedArrayLength()),
|
| + receiver, effect, control);
|
| +
|
| + // Load the buffer for the {receiver}.
|
| + buffer = effect = graph()->NewNode(
|
| + simplified()->LoadField(AccessBuilder::ForJSArrayBufferViewBuffer()),
|
| + receiver, effect, control);
|
| +
|
| + // Load the elements for the {receiver}.
|
| + Node* elements = effect = graph()->NewNode(
|
| + simplified()->LoadField(AccessBuilder::ForJSObjectElements()),
|
| + receiver, effect, control);
|
| +
|
| + // Load the base and external pointer for the {receiver}s {elements}.
|
| + base_pointer = effect = graph()->NewNode(
|
| + simplified()->LoadField(
|
| + AccessBuilder::ForFixedTypedArrayBaseBasePointer()),
|
| + elements, effect, control);
|
| + external_pointer = effect = graph()->NewNode(
|
| + simplified()->LoadField(
|
| + AccessBuilder::ForFixedTypedArrayBaseExternalPointer()),
|
| + elements, effect, control);
|
| + }
|
|
|
| - // Check if the {receiver}s buffer was neutered.
|
| - Node* buffer = effect = graph()->NewNode(
|
| - simplified()->LoadField(AccessBuilder::ForJSArrayBufferViewBuffer()),
|
| - receiver, effect, control);
|
| + // Default to zero if the {receiver}s buffer was neutered.
|
| Node* check = effect = graph()->NewNode(
|
| simplified()->ArrayBufferWasNeutered(), buffer, effect, control);
|
| -
|
| - // Default to zero if the {receiver}s buffer was neutered.
|
| length = graph()->NewNode(
|
| common()->Select(MachineRepresentation::kTagged, BranchHint::kFalse),
|
| check, jsgraph()->ZeroConstant(), length);
|
| @@ -1211,16 +1234,6 @@ JSNativeContextSpecialization::BuildElementAccess(
|
| length, effect, control);
|
| }
|
|
|
| - // Load the base and external pointer for the {receiver}.
|
| - Node* base_pointer = effect = graph()->NewNode(
|
| - simplified()->LoadField(
|
| - AccessBuilder::ForFixedTypedArrayBaseBasePointer()),
|
| - elements, effect, control);
|
| - Node* external_pointer = effect = graph()->NewNode(
|
| - simplified()->LoadField(
|
| - AccessBuilder::ForFixedTypedArrayBaseExternalPointer()),
|
| - elements, effect, control);
|
| -
|
| // Access the actual element.
|
| ExternalArrayType external_array_type =
|
| GetArrayTypeFromElementsKind(elements_kind);
|
| @@ -1280,6 +1293,20 @@ JSNativeContextSpecialization::BuildElementAccess(
|
| }
|
| }
|
| } else {
|
| + // Load the elements for the {receiver}.
|
| + Node* elements = effect = graph()->NewNode(
|
| + simplified()->LoadField(AccessBuilder::ForJSObjectElements()), receiver,
|
| + effect, control);
|
| +
|
| + // Don't try to store to a copy-on-write backing store.
|
| + if (access_mode == AccessMode::kStore &&
|
| + IsFastSmiOrObjectElementsKind(elements_kind) &&
|
| + store_mode != STORE_NO_TRANSITION_HANDLE_COW) {
|
| + effect =
|
| + graph()->NewNode(simplified()->CheckMaps(1), elements,
|
| + jsgraph()->FixedArrayMapConstant(), effect, control);
|
| + }
|
| +
|
| // Check if the {receiver} is a JSArray.
|
| bool receiver_is_jsarray = HasOnlyJSArrayMaps(receiver_maps);
|
|
|
| @@ -1468,6 +1495,33 @@ JSNativeContextSpecialization::InlineApiCall(
|
| return ValueEffectControl(value0, effect0, control0);
|
| }
|
|
|
| +Node* JSNativeContextSpecialization::BuildCheckHeapObject(Node* receiver,
|
| + Node** effect,
|
| + Node* control) {
|
| + switch (receiver->opcode()) {
|
| + case IrOpcode::kHeapConstant:
|
| + case IrOpcode::kJSCreate:
|
| + case IrOpcode::kJSCreateArguments:
|
| + case IrOpcode::kJSCreateArray:
|
| + case IrOpcode::kJSCreateClosure:
|
| + case IrOpcode::kJSCreateIterResultObject:
|
| + case IrOpcode::kJSCreateLiteralArray:
|
| + case IrOpcode::kJSCreateLiteralObject:
|
| + case IrOpcode::kJSCreateLiteralRegExp:
|
| + case IrOpcode::kJSConvertReceiver:
|
| + case IrOpcode::kJSToName:
|
| + case IrOpcode::kJSToString:
|
| + case IrOpcode::kJSToObject:
|
| + case IrOpcode::kJSTypeOf: {
|
| + return receiver;
|
| + }
|
| + default: {
|
| + return *effect = graph()->NewNode(simplified()->CheckHeapObject(),
|
| + receiver, *effect, control);
|
| + }
|
| + }
|
| +}
|
| +
|
| Node* JSNativeContextSpecialization::BuildCheckMaps(
|
| Node* receiver, Node* effect, Node* control,
|
| std::vector<Handle<Map>> const& maps) {
|
|
|