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.