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

Unified Diff: src/code-stub-assembler.cc

Issue 1980483003: [es6] Reintroduce the instanceof operator in the backends. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Igors comments. Created 4 years, 7 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/code-stub-assembler.h ('k') | src/code-stubs.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/code-stub-assembler.cc
diff --git a/src/code-stub-assembler.cc b/src/code-stub-assembler.cc
index e5041756644d52698ce5b3702f1150397afcb544..c047aab2e31584d0b37df129264c9c0278795101 100644
--- a/src/code-stub-assembler.cc
+++ b/src/code-stub-assembler.cc
@@ -1416,5 +1416,141 @@ void CodeStubAssembler::TryLookupElement(Node* object, Node* map,
}
}
+Node* CodeStubAssembler::OrdinaryHasInstance(Node* context, Node* callable,
+ Node* object) {
+ Variable var_result(this, MachineRepresentation::kTagged);
+ Label return_false(this), return_true(this),
+ return_runtime(this, Label::kDeferred), return_result(this);
+
+ // Goto runtime if {object} is a Smi.
+ GotoIf(WordIsSmi(object), &return_runtime);
+
+ // Load map of {object}.
+ Node* object_map = LoadMap(object);
+
+ // Lookup the {callable} and {object} map in the global instanceof cache.
+ // Note: This is safe because we clear the global instanceof cache whenever
+ // we change the prototype of any object.
+ Node* instanceof_cache_function =
+ LoadRoot(Heap::kInstanceofCacheFunctionRootIndex);
+ Node* instanceof_cache_map = LoadRoot(Heap::kInstanceofCacheMapRootIndex);
+ {
+ Label instanceof_cache_miss(this);
+ GotoUnless(WordEqual(instanceof_cache_function, callable),
+ &instanceof_cache_miss);
+ GotoUnless(WordEqual(instanceof_cache_map, object_map),
+ &instanceof_cache_miss);
+ var_result.Bind(LoadRoot(Heap::kInstanceofCacheAnswerRootIndex));
+ Goto(&return_result);
+ Bind(&instanceof_cache_miss);
+ }
+
+ // Goto runtime if {callable} is a Smi.
+ GotoIf(WordIsSmi(callable), &return_runtime);
+
+ // Load map of {callable}.
+ Node* callable_map = LoadMap(callable);
+
+ // Goto runtime if {callable} is not a JSFunction.
+ Node* callable_instance_type = LoadMapInstanceType(callable_map);
+ GotoUnless(
+ Word32Equal(callable_instance_type, Int32Constant(JS_FUNCTION_TYPE)),
+ &return_runtime);
+
+ // Goto runtime if {callable} is not a constructor or has
+ // a non-instance "prototype".
+ Node* callable_bitfield = LoadMapBitField(callable_map);
+ GotoUnless(
+ Word32Equal(Word32And(callable_bitfield,
+ Int32Constant((1 << Map::kHasNonInstancePrototype) |
+ (1 << Map::kIsConstructor))),
+ Int32Constant(1 << Map::kIsConstructor)),
+ &return_runtime);
+
+ // Get the "prototype" (or initial map) of the {callable}.
+ Node* callable_prototype =
+ LoadObjectField(callable, JSFunction::kPrototypeOrInitialMapOffset);
+ {
+ Variable var_callable_prototype(this, MachineRepresentation::kTagged);
+ Label callable_prototype_valid(this);
+ var_callable_prototype.Bind(callable_prototype);
+
+ // Resolve the "prototype" if the {callable} has an initial map. Afterwards
+ // the {callable_prototype} will be either the JSReceiver prototype object
+ // or the hole value, which means that no instances of the {callable} were
+ // created so far and hence we should return false.
+ Node* callable_prototype_instance_type =
+ LoadInstanceType(callable_prototype);
+ GotoUnless(
+ Word32Equal(callable_prototype_instance_type, Int32Constant(MAP_TYPE)),
+ &callable_prototype_valid);
+ var_callable_prototype.Bind(
+ LoadObjectField(callable_prototype, Map::kPrototypeOffset));
+ Goto(&callable_prototype_valid);
+ Bind(&callable_prototype_valid);
+ callable_prototype = var_callable_prototype.value();
+ }
+
+ // Update the global instanceof cache with the current {object} map and
+ // {callable}. The cached answer will be set when it is known below.
+ StoreRoot(Heap::kInstanceofCacheFunctionRootIndex, callable);
+ StoreRoot(Heap::kInstanceofCacheMapRootIndex, object_map);
+
+ // Loop through the prototype chain looking for the {callable} prototype.
+ Variable var_object_map(this, MachineRepresentation::kTagged);
+ var_object_map.Bind(object_map);
+ Label loop(this, &var_object_map);
+ Goto(&loop);
+ Bind(&loop);
+ {
+ Node* object_map = var_object_map.value();
+
+ // Check if the current {object} needs to be access checked.
+ Node* object_bitfield = LoadMapBitField(object_map);
+ GotoUnless(
+ Word32Equal(Word32And(object_bitfield,
+ Int32Constant(1 << Map::kIsAccessCheckNeeded)),
+ Int32Constant(0)),
+ &return_runtime);
+
+ // Check if the current {object} is a proxy.
+ Node* object_instance_type = LoadMapInstanceType(object_map);
+ GotoIf(Word32Equal(object_instance_type, Int32Constant(JS_PROXY_TYPE)),
+ &return_runtime);
+
+ // Check the current {object} prototype.
+ Node* object_prototype = LoadMapPrototype(object_map);
+ GotoIf(WordEqual(object_prototype, callable_prototype), &return_true);
+ GotoIf(WordEqual(object_prototype, NullConstant()), &return_false);
+
+ // Continue with the prototype.
+ var_object_map.Bind(LoadMap(object_prototype));
+ Goto(&loop);
+ }
+
+ Bind(&return_true);
+ StoreRoot(Heap::kInstanceofCacheAnswerRootIndex, BooleanConstant(true));
+ var_result.Bind(BooleanConstant(true));
+ Goto(&return_result);
+
+ Bind(&return_false);
+ StoreRoot(Heap::kInstanceofCacheAnswerRootIndex, BooleanConstant(false));
+ var_result.Bind(BooleanConstant(false));
+ Goto(&return_result);
+
+ Bind(&return_runtime);
+ {
+ // Invalidate the global instanceof cache.
+ StoreRoot(Heap::kInstanceofCacheFunctionRootIndex, SmiConstant(0));
+ // Fallback to the runtime implementation.
+ var_result.Bind(
+ CallRuntime(Runtime::kOrdinaryHasInstance, context, callable, object));
+ }
+ Goto(&return_result);
+
+ Bind(&return_result);
+ return var_result.value();
+}
+
} // namespace internal
} // namespace v8
« no previous file with comments | « src/code-stub-assembler.h ('k') | src/code-stubs.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698