Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(144)

Unified Diff: src/compiler/js-native-context-specialization.cc

Issue 2934893002: [builtins] Properly optimize Object.prototype.isPrototypeOf. (Closed)
Patch Set: Address feedback. Created 3 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/compiler/js-native-context-specialization.h ('k') | src/compiler/js-operator.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 b1d3da63447a94190935804ad9bbbc212b763206..cd54937a94bce122b02702bd1c72aaa090a3e042 100644
--- a/src/compiler/js-native-context-specialization.cc
+++ b/src/compiler/js-native-context-specialization.cc
@@ -274,10 +274,6 @@ Reduction JSNativeContextSpecialization::ReduceJSOrdinaryHasInstance(
DCHECK_EQ(IrOpcode::kJSOrdinaryHasInstance, node->opcode());
Node* constructor = NodeProperties::GetValueInput(node, 0);
Node* object = NodeProperties::GetValueInput(node, 1);
- Node* context = NodeProperties::GetContextInput(node);
- Node* frame_state = NodeProperties::GetFrameStateInput(node);
- Node* effect = NodeProperties::GetEffectInput(node);
- Node* control = NodeProperties::GetControlInput(node);
// Check if the {constructor} is known at compile time.
HeapObjectMatcher m(constructor);
@@ -311,143 +307,13 @@ Reduction JSNativeContextSpecialization::ReduceJSOrdinaryHasInstance(
// Install a code dependency on the {function}s initial map.
Handle<Map> initial_map(function->initial_map(), isolate());
dependencies()->AssumeInitialMapCantChange(initial_map);
- Handle<JSReceiver> function_prototype =
- handle(JSReceiver::cast(initial_map->prototype()), isolate());
-
- // Check if we can constant-fold the prototype chain walk
- // for the given {object} and the {function_prototype}.
- InferHasInPrototypeChainResult result =
- InferHasInPrototypeChain(object, effect, function_prototype);
- if (result != kMayBeInPrototypeChain) {
- Node* value = jsgraph()->BooleanConstant(result == kIsInPrototypeChain);
- ReplaceWithValue(node, value, effect, control);
- return Replace(value);
- }
+ Node* prototype =
+ jsgraph()->Constant(handle(initial_map->prototype(), isolate()));
- Node* prototype = jsgraph()->Constant(function_prototype);
-
- Node* check0 = graph()->NewNode(simplified()->ObjectIsSmi(), object);
- Node* branch0 = graph()->NewNode(common()->Branch(BranchHint::kFalse),
- check0, control);
-
- Node* if_true0 = graph()->NewNode(common()->IfTrue(), branch0);
- Node* etrue0 = effect;
- Node* vtrue0 = jsgraph()->FalseConstant();
-
- control = graph()->NewNode(common()->IfFalse(), branch0);
-
- // Loop through the {object}s prototype chain looking for the {prototype}.
- Node* loop = control =
- graph()->NewNode(common()->Loop(2), control, control);
- Node* eloop = effect =
- graph()->NewNode(common()->EffectPhi(2), effect, effect, loop);
- Node* vloop = object =
- graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
- object, object, loop);
-
- // Load the {object} map and instance type.
- Node* object_map = effect =
- graph()->NewNode(simplified()->LoadField(AccessBuilder::ForMap()),
- object, effect, control);
- Node* object_instance_type = effect = graph()->NewNode(
- simplified()->LoadField(AccessBuilder::ForMapInstanceType()),
- object_map, effect, control);
-
- // Check if the {object} is a special receiver, because for special
- // receivers, i.e. proxies or API objects that need access checks,
- // we have to use the %HasInPrototypeChain runtime function instead.
- Node* check1 = graph()->NewNode(
- simplified()->NumberLessThanOrEqual(), object_instance_type,
- jsgraph()->Constant(LAST_SPECIAL_RECEIVER_TYPE));
- Node* branch1 = graph()->NewNode(common()->Branch(BranchHint::kFalse),
- check1, control);
-
- control = graph()->NewNode(common()->IfFalse(), branch1);
-
- Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1);
- Node* etrue1 = effect;
- Node* vtrue1;
-
- // Check if the {object} is not a receiver at all.
- Node* check10 =
- graph()->NewNode(simplified()->NumberLessThan(), object_instance_type,
- jsgraph()->Constant(FIRST_JS_RECEIVER_TYPE));
- Node* branch10 = graph()->NewNode(common()->Branch(BranchHint::kTrue),
- check10, if_true1);
-
- // A primitive value cannot match the {prototype} we're looking for.
- if_true1 = graph()->NewNode(common()->IfTrue(), branch10);
- vtrue1 = jsgraph()->FalseConstant();
-
- Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch10);
- Node* efalse1 = etrue1;
- Node* vfalse1;
- {
- // Slow path, need to call the %HasInPrototypeChain runtime function.
- vfalse1 = efalse1 = if_false1 = graph()->NewNode(
- javascript()->CallRuntime(Runtime::kHasInPrototypeChain), object,
- prototype, context, frame_state, efalse1, if_false1);
-
- // Replace any potential {IfException} uses of {node} to catch
- // exceptions from this %HasInPrototypeChain runtime call instead.
- Node* on_exception = nullptr;
- if (NodeProperties::IsExceptionalCall(node, &on_exception)) {
- NodeProperties::ReplaceControlInput(on_exception, vfalse1);
- NodeProperties::ReplaceEffectInput(on_exception, efalse1);
- if_false1 = graph()->NewNode(common()->IfSuccess(), vfalse1);
- Revisit(on_exception);
- }
- }
-
- // Load the {object} prototype.
- Node* object_prototype = effect = graph()->NewNode(
- simplified()->LoadField(AccessBuilder::ForMapPrototype()), object_map,
- effect, control);
-
- // Check if we reached the end of {object}s prototype chain.
- Node* check2 =
- graph()->NewNode(simplified()->ReferenceEqual(), object_prototype,
- jsgraph()->NullConstant());
- Node* branch2 = graph()->NewNode(common()->Branch(), check2, control);
-
- Node* if_true2 = graph()->NewNode(common()->IfTrue(), branch2);
- Node* etrue2 = effect;
- Node* vtrue2 = jsgraph()->FalseConstant();
-
- control = graph()->NewNode(common()->IfFalse(), branch2);
-
- // Check if we reached the {prototype}.
- Node* check3 = graph()->NewNode(simplified()->ReferenceEqual(),
- object_prototype, prototype);
- Node* branch3 = graph()->NewNode(common()->Branch(), check3, control);
-
- Node* if_true3 = graph()->NewNode(common()->IfTrue(), branch3);
- Node* etrue3 = effect;
- Node* vtrue3 = jsgraph()->TrueConstant();
-
- control = graph()->NewNode(common()->IfFalse(), branch3);
-
- // Close the loop.
- vloop->ReplaceInput(1, object_prototype);
- eloop->ReplaceInput(1, effect);
- loop->ReplaceInput(1, control);
-
- control = graph()->NewNode(common()->Merge(5), if_true0, if_true1,
- if_true2, if_true3, if_false1);
- effect = graph()->NewNode(common()->EffectPhi(5), etrue0, etrue1, etrue2,
- etrue3, efalse1, control);
-
- // Morph the {node} into an appropriate Phi.
- ReplaceWithValue(node, node, effect, control);
- node->ReplaceInput(0, vtrue0);
- node->ReplaceInput(1, vtrue1);
- node->ReplaceInput(2, vtrue2);
- node->ReplaceInput(3, vtrue3);
- node->ReplaceInput(4, vfalse1);
- node->ReplaceInput(5, control);
- node->TrimInputCount(6);
- NodeProperties::ChangeOp(
- node, common()->Phi(MachineRepresentation::kTagged, 5));
+ // Lower the {node} to JSHasInPrototypeChain.
+ NodeProperties::ReplaceValueInput(node, object, 0);
+ NodeProperties::ReplaceValueInput(node, prototype, 1);
+ NodeProperties::ChangeOp(node, javascript()->HasInPrototypeChain());
return Changed(node);
}
}
@@ -2445,57 +2311,6 @@ bool JSNativeContextSpecialization::CanTreatHoleAsUndefined(
return true;
}
-JSNativeContextSpecialization::InferHasInPrototypeChainResult
-JSNativeContextSpecialization::InferHasInPrototypeChain(
- Node* receiver, Node* effect, Handle<JSReceiver> prototype) {
- ZoneHandleSet<Map> receiver_maps;
- NodeProperties::InferReceiverMapsResult result =
- NodeProperties::InferReceiverMaps(receiver, effect, &receiver_maps);
- if (result == NodeProperties::kNoReceiverMaps) return kMayBeInPrototypeChain;
-
- // Check if either all or none of the {receiver_maps} have the given
- // {prototype} in their prototype chain.
- bool all = true;
- bool none = true;
- for (size_t i = 0; i < receiver_maps.size(); ++i) {
- Handle<Map> receiver_map = receiver_maps[i];
- if (receiver_map->instance_type() <= LAST_SPECIAL_RECEIVER_TYPE) {
- return kMayBeInPrototypeChain;
- }
- if (result == NodeProperties::kUnreliableReceiverMaps) {
- // In case of an unreliable {result} we need to ensure that all
- // {receiver_maps} are stable, because otherwise we cannot trust
- // the {receiver_maps} information, since arbitrary side-effects
- // may have happened.
- if (!receiver_map->is_stable()) {
- return kMayBeInPrototypeChain;
- }
- }
- for (PrototypeIterator j(receiver_map);; j.Advance()) {
- if (j.IsAtEnd()) {
- all = false;
- break;
- }
- Handle<JSReceiver> const current =
- PrototypeIterator::GetCurrent<JSReceiver>(j);
- if (current.is_identical_to(prototype)) {
- none = false;
- break;
- }
- if (!current->map()->is_stable() ||
- current->map()->instance_type() <= LAST_SPECIAL_RECEIVER_TYPE) {
- return kMayBeInPrototypeChain;
- }
- }
- }
- DCHECK_IMPLIES(all, !none);
- DCHECK_IMPLIES(none, !all);
-
- if (all) return kIsInPrototypeChain;
- if (none) return kIsNotInPrototypeChain;
- return kMayBeInPrototypeChain;
-}
-
bool JSNativeContextSpecialization::ExtractReceiverMaps(
Node* receiver, Node* effect, FeedbackNexus const& nexus,
MapHandles* receiver_maps) {
« no previous file with comments | « src/compiler/js-native-context-specialization.h ('k') | src/compiler/js-operator.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698