Reviewers: Dmitry Lomov (chromium), Toon Verwaest,

Message:
Motivation: I want to use GetPrototype in the default constructor for classes.

Description:
Optimize GetPrototype

This introduces Hydrogen for %_GetPrototype. The code falls back on
runtime if the object needs access checks or if its prototype is a
hidden prototype.

BUG=None
LOG=Y
[email protected]

Please review this at https://codereview.chromium.org/756423006/

Base URL: https://chromium.googlesource.com/v8/v8.git@master

Affected files (+62, -9 lines):
  M src/array.js
  M src/hydrogen.cc
  M src/hydrogen-instructions.h
  M src/messages.js
  M src/runtime/runtime.h
  M src/v8natives.js


Index: src/array.js
diff --git a/src/array.js b/src/array.js
index ba4ce60cf9c1b5a5e8e0181266ef8763ee8925e6..c702d8caf3a53a02d191f9076d81ca4dd9a2245b 100644
--- a/src/array.js
+++ b/src/array.js
@@ -984,7 +984,7 @@ function ArraySort(comparefn) {
   // of a prototype property.
   var CopyFromPrototype = function CopyFromPrototype(obj, length) {
     var max = 0;
- for (var proto = %GetPrototype(obj); proto; proto = %GetPrototype(proto)) { + for (var proto = %_GetPrototype(obj); proto; proto = %_GetPrototype(proto)) {
       var indices = %GetArrayKeys(proto, length);
       if (IS_NUMBER(indices)) {
         // It's an interval.
@@ -1013,7 +1013,7 @@ function ArraySort(comparefn) {
   // where a prototype of obj has an element. I.e., shadow all prototype
   // elements in that range.
   var ShadowPrototypeElements = function(obj, from, to) {
- for (var proto = %GetPrototype(obj); proto; proto = %GetPrototype(proto)) { + for (var proto = %_GetPrototype(obj); proto; proto = %_GetPrototype(proto)) {
       var indices = %GetArrayKeys(proto, to);
       if (IS_NUMBER(indices)) {
         // It's an interval.
@@ -1081,7 +1081,7 @@ function ArraySort(comparefn) {
     }
     for (i = length - num_holes; i < length; i++) {
// For compatability with Webkit, do not expose elements in the prototype.
-      if (i in %GetPrototype(obj)) {
+      if (i in %_GetPrototype(obj)) {
         obj[i] = UNDEFINED;
       } else {
         delete obj[i];
Index: src/hydrogen-instructions.h
diff --git a/src/hydrogen-instructions.h b/src/hydrogen-instructions.h
index b56e9215ab35d5d4c22b11f8eab3af9128fc6e58..8518fdca09de7944a0784099164fc6ced420ea3a 100644
--- a/src/hydrogen-instructions.h
+++ b/src/hydrogen-instructions.h
@@ -6179,6 +6179,10 @@ class HObjectAccess FINAL {
     return HObjectAccess(kMaps, JSObject::kMapOffset);
   }

+  static HObjectAccess ForPrototype() {
+    return HObjectAccess(kMaps, Map::kPrototypeOffset);
+  }
+
   static HObjectAccess ForMapAsInteger32() {
     return HObjectAccess(kMaps, JSObject::kMapOffset,
                          Representation::Integer32());
Index: src/hydrogen.cc
diff --git a/src/hydrogen.cc b/src/hydrogen.cc
index 8570b33ce08a509bc08b5b03250327f116080d87..d4dc0db37dade6537dec39a4427c098380ca2358 100644
--- a/src/hydrogen.cc
+++ b/src/hydrogen.cc
@@ -12390,6 +12390,55 @@ void HOptimizedGraphBuilder::GenerateDebugIsActive(CallRuntime* call) {
 }


+void HOptimizedGraphBuilder::GenerateGetPrototype(CallRuntime* call) {
+  DCHECK(call->arguments()->length() == 1);
+  CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
+  HValue* object = Pop();
+
+  NoObservableSideEffectsScope no_effects(this);
+
+  HValue* map = Add<HLoadNamedField>(object, static_cast<HValue*>(NULL),
+                                     HObjectAccess::ForMap());
+  HValue* bit_field = Add<HLoadNamedField>(map, static_cast<HValue*>(NULL),
+ HObjectAccess::ForMapBitField());
+  HValue* is_access_check_needed_mask =
+      Add<HConstant>(1 << Map::kIsAccessCheckNeeded);
+  HValue* is_access_check_needed_test = AddUncasted<HBitwise>(
+      Token::BIT_AND, bit_field, is_access_check_needed_mask);
+
+  HValue* proto = Add<HLoadNamedField>(map, static_cast<HValue*>(NULL),
+                                       HObjectAccess::ForPrototype());
+ HValue* proto_map = Add<HLoadNamedField>(proto, static_cast<HValue*>(NULL),
+                                           HObjectAccess::ForMap());
+  HValue* proto_bit_field = Add<HLoadNamedField>(
+ proto_map, static_cast<HValue*>(NULL), HObjectAccess::ForMapBitField());
+  HValue* is_hidden_prototype_mask =
+      Add<HConstant>(1 << Map::kIsHiddenPrototype);
+  HValue* is_hidden_prototype_test = AddUncasted<HBitwise>(
+      Token::BIT_AND, proto_bit_field, is_hidden_prototype_mask);
+
+  {
+    IfBuilder needs_runtime(this);
+    needs_runtime.If<HCompareNumericAndBranch>(
+        is_access_check_needed_test, graph()->GetConstant0(), Token::NE);
+    needs_runtime.OrIf<HCompareNumericAndBranch>(
+        is_hidden_prototype_test, graph()->GetConstant0(), Token::NE);
+
+    needs_runtime.Then();
+    {
+      Add<HPushArguments>(object);
+      Push(Add<HCallRuntime>(
+ call->name(), Runtime::FunctionForId(Runtime::kGetPrototype), 1));
+    }
+
+    needs_runtime.Else();
+    Push(proto);
+  }
+
+  return ast_context()->ReturnValue(Pop());
+}
+
+
 #undef CHECK_BAILOUT
 #undef CHECK_ALIVE

Index: src/messages.js
diff --git a/src/messages.js b/src/messages.js
index 431077745c02b48547acfa2d0207d34d1a05b4e8..bf47a45c9d21583b4fadb11b59fdaa3b6e23995c 100644
--- a/src/messages.js
+++ b/src/messages.js
@@ -1151,7 +1151,7 @@ var StackTraceGetter = function() {
       if (IS_UNDEFINED(stack_trace)) {
         // Neither formatted nor structured stack trace available.
         // Look further up the prototype chain.
-        holder = %GetPrototype(holder);
+        holder = %_GetPrototype(holder);
         continue;
       }
       formatted_stack_trace = FormatStackTrace(holder, stack_trace);
@@ -1255,7 +1255,7 @@ function GetPropertyWithoutInvokingMonkeyGetters(error, name) {
   var current = error;
   // Climb the prototype chain until we find the holder.
   while (current && !%HasOwnProperty(current, name)) {
-    current = %GetPrototype(current);
+    current = %_GetPrototype(current);
   }
   if (IS_NULL(current)) return UNDEFINED;
   if (!IS_OBJECT(current)) return error[name];
Index: src/runtime/runtime.h
diff --git a/src/runtime/runtime.h b/src/runtime/runtime.h
index 4d2b3d8183329f0391d7037b0da3d0ef679cb5a1..9355fafd107bc85baacf84f679b394cbad5ed260 100644
--- a/src/runtime/runtime.h
+++ b/src/runtime/runtime.h
@@ -45,7 +45,6 @@ namespace internal {
   F(IsSloppyModeFunction, 1, 1)                            \
   F(GetDefaultReceiver, 1, 1)                              \
                                                            \
-  F(GetPrototype, 1, 1)                                    \
   F(SetPrototype, 2, 1)                                    \
   F(InternalSetPrototype, 2, 1)                            \
   F(IsInPrototypeChain, 2, 1)                              \
@@ -733,7 +732,8 @@ namespace internal {
   F(SetGetSize, 1, 1)                     \
   F(SetHas, 2, 1)                         \
   /* Arrays */                            \
-  F(HasFastPackedElements, 1, 1)
+  F(HasFastPackedElements, 1, 1)          \
+  F(GetPrototype, 1, 1)


//---------------------------------------------------------------------------
Index: src/v8natives.js
diff --git a/src/v8natives.js b/src/v8natives.js
index bad0154b0ba0ba5bb7425a38cdd9aafb82783de6..02294b340ab4607557f55daee6886c46b34d9e92 100644
--- a/src/v8natives.js
+++ b/src/v8natives.js
@@ -973,7 +973,7 @@ function ObjectGetPrototypeOf(obj) {
   if (!IS_SPEC_OBJECT(obj)) {
     throw MakeTypeError("called_on_non_object", ["Object.getPrototypeOf"]);
   }
-  return %GetPrototype(obj);
+  return %_GetPrototype(obj);
 }

 // ES6 section 19.1.2.19.
@@ -1361,7 +1361,7 @@ function ObjectIs(obj1, obj2) {

 // ECMA-262, Edition 6, section B.2.2.1.1
 function ObjectGetProto() {
-  return %GetPrototype(ToObject(this));
+  return %_GetPrototype(ToObject(this));
 }




--
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
--- You received this message because you are subscribed to the Google Groups "v8-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/d/optout.

Reply via email to