Commit 5339e546 authored by Marja Hölttä's avatar Marja Hölttä Committed by Commit Bot

[super property speed] Add a byte code for super property access

This is the first step in a series of CLs. The goal is to make
super property access faster.

Design doc: https://docs.google.com/document/d/1b_wgtExmJDLb8206jpJol-g4vJAxPs1XjEx95hwRboI/edit?usp=sharing

This CL:
- Add bytecode LdaNamedPropertyFromSuper
- IGNITION_HANDLER just calls Runtime::LoadFromSuper
- JSGenericLowering::LowerJSLoadNamedFromSuper just replaces the node
with a runtime call to Runtime::LoadFromSuper


Bug: v8:9237
Change-Id: Id28e935294c5068dd6c54e6b860a77d61517fff5
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2327912
Commit-Queue: Marja Hölttä <marja@chromium.org>
Reviewed-by: 's avatarGeorg Neis <neis@chromium.org>
Reviewed-by: 's avatarIgor Sheludko <ishell@chromium.org>
Reviewed-by: 's avatarMythri Alle <mythria@chromium.org>
Reviewed-by: 's avatarLeszek Swirski <leszeks@chromium.org>
Cr-Commit-Position: refs/heads/master@{#69604}
parent c316d0ed
......@@ -1996,6 +1996,20 @@ void BytecodeGraphBuilder::VisitLdaNamedPropertyNoFeedback() {
environment()->BindAccumulator(node, Environment::kAttachFrameState);
}
void BytecodeGraphBuilder::VisitLdaNamedPropertyFromSuper() {
PrepareEagerCheckpoint();
Node* receiver =
environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0));
Node* home_object = environment()->LookupAccumulator();
NameRef name(broker(),
bytecode_iterator().GetConstantForIndexOperand(1, isolate()));
const Operator* op = javascript()->LoadNamedFromSuper(name.object());
// TODO(marja, v8:9237): Use lowering.
Node* node = NewNode(op, receiver, home_object);
environment()->BindAccumulator(node, Environment::kAttachFrameState);
}
void BytecodeGraphBuilder::VisitLdaKeyedProperty() {
PrepareEagerCheckpoint();
Node* key = environment()->LookupAccumulator();
......
......@@ -315,6 +315,13 @@ void JSGenericLowering::LowerJSLoadNamed(Node* node) {
}
}
void JSGenericLowering::LowerJSLoadNamedFromSuper(Node* node) {
JSLoadNamedFromSuperNode n(node);
NamedAccess const& p = n.Parameters();
node->InsertInput(zone(), 2, jsgraph()->HeapConstant(p.name()));
ReplaceWithRuntimeCall(node, Runtime::kLoadFromSuper);
}
void JSGenericLowering::LowerJSLoadGlobal(Node* node) {
JSLoadGlobalNode n(node);
const LoadGlobalParameters& p = n.Parameters();
......
......@@ -171,6 +171,13 @@ Reduction JSHeapCopyReducer::Reduce(Node* node) {
}
break;
}
case IrOpcode::kJSLoadNamedFromSuper: {
// TODO(marja, v8:9237): Process feedback once it's added to the byte
// code.
NamedAccess const& p = NamedAccessOf(node->op());
NameRef name(broker(), p.name());
break;
}
case IrOpcode::kJSStoreNamed: {
NamedAccess const& p = NamedAccessOf(node->op());
NameRef name(broker(), p.name());
......
......@@ -287,6 +287,7 @@ std::ostream& operator<<(std::ostream& os, NamedAccess const& p) {
NamedAccess const& NamedAccessOf(const Operator* op) {
DCHECK(op->opcode() == IrOpcode::kJSLoadNamed ||
op->opcode() == IrOpcode::kJSLoadNamedFromSuper ||
op->opcode() == IrOpcode::kJSStoreNamed);
return OpParameter<NamedAccess>(op);
}
......@@ -918,6 +919,19 @@ const Operator* JSOperatorBuilder::LoadNamed(Handle<Name> name,
access); // parameter
}
const Operator* JSOperatorBuilder::LoadNamedFromSuper(Handle<Name> name) {
static constexpr int kReceiver = 1;
static constexpr int kHomeObject = 1;
static constexpr int kArity = kReceiver + kHomeObject;
// TODO(marja, v8:9237): Use real feedback.
NamedAccess access(LanguageMode::kSloppy, name, FeedbackSource());
return zone()->New<Operator1<NamedAccess>>( // --
IrOpcode::kJSLoadNamedFromSuper, Operator::kNoProperties, // opcode
"JSLoadNamedFromSuper", // name
kArity, 1, 1, 1, 1, 2, // counts
access); // parameter
}
const Operator* JSOperatorBuilder::LoadProperty(
FeedbackSource const& feedback) {
PropertyAccess access(LanguageMode::kSloppy, feedback);
......
......@@ -921,6 +921,7 @@ class V8_EXPORT_PRIVATE JSOperatorBuilder final
const Operator* LoadProperty(FeedbackSource const& feedback);
const Operator* LoadNamed(Handle<Name> name, FeedbackSource const& feedback);
const Operator* LoadNamedFromSuper(Handle<Name> name);
const Operator* StoreProperty(LanguageMode language_mode,
FeedbackSource const& feedback);
......@@ -1389,6 +1390,22 @@ class JSLoadNamedNode final : public JSNodeWrapperBase {
#undef INPUTS
};
class JSLoadNamedFromSuperNode final : public JSNodeWrapperBase {
public:
explicit constexpr JSLoadNamedFromSuperNode(Node* node)
: JSNodeWrapperBase(node) {
CONSTEXPR_DCHECK(node->opcode() == IrOpcode::kJSLoadNamedFromSuper);
}
const NamedAccess& Parameters() const { return NamedAccessOf(node()->op()); }
#define INPUTS(V) \
V(Receiver, receiver, 0, Object) \
V(Object, home_object, 1, Object)
INPUTS(DEFINE_INPUT_ACCESSORS)
#undef INPUTS
};
class JSStoreNamedNode final : public JSNodeWrapperBase {
public:
explicit constexpr JSStoreNamedNode(Node* node) : JSNodeWrapperBase(node) {
......
......@@ -170,6 +170,7 @@
JS_CREATE_OP_LIST(V) \
V(JSLoadProperty) \
V(JSLoadNamed) \
V(JSLoadNamedFromSuper) \
V(JSLoadGlobal) \
V(JSStoreProperty) \
V(JSStoreNamed) \
......
......@@ -80,6 +80,7 @@ bool OperatorProperties::NeedsExactContext(const Operator* op) {
case IrOpcode::kJSLoadContext:
case IrOpcode::kJSLoadModule:
case IrOpcode::kJSLoadNamed:
case IrOpcode::kJSLoadNamedFromSuper:
case IrOpcode::kJSLoadProperty:
case IrOpcode::kJSStoreContext:
case IrOpcode::kJSStoreDataPropertyInLiteral:
......@@ -193,6 +194,7 @@ bool OperatorProperties::HasFrameStateInput(const Operator* op) {
// Property access operations
case IrOpcode::kJSLoadNamed:
case IrOpcode::kJSLoadNamedFromSuper:
case IrOpcode::kJSStoreNamed:
case IrOpcode::kJSLoadProperty:
case IrOpcode::kJSStoreProperty:
......
......@@ -198,6 +198,7 @@ namespace compiler {
V(LdaLookupSlot) \
V(LdaLookupSlotInsideTypeof) \
V(LdaNamedProperty) \
V(LdaNamedPropertyFromSuper) \
V(LdaNamedPropertyNoFeedback) \
V(LdaNull) \
V(Ldar) \
......@@ -3260,6 +3261,13 @@ void SerializerForBackgroundCompilation::VisitLdaNamedProperty(
ProcessNamedPropertyAccess(receiver, name, slot, AccessMode::kLoad);
}
void SerializerForBackgroundCompilation::VisitLdaNamedPropertyFromSuper(
BytecodeArrayIterator* iterator) {
NameRef(broker(),
iterator->GetConstantForIndexOperand(1, broker()->isolate()));
// TODO(marja, v8:9237): Process feedback once it's added to the byte code.
}
// TODO(neis): Do feedback-independent serialization also for *NoFeedback
// bytecodes.
void SerializerForBackgroundCompilation::VisitLdaNamedPropertyNoFeedback(
......
......@@ -1307,6 +1307,10 @@ Type Typer::Visitor::TypeJSLoadProperty(Node* node) {
Type Typer::Visitor::TypeJSLoadNamed(Node* node) { return Type::NonInternal(); }
Type Typer::Visitor::TypeJSLoadNamedFromSuper(Node* node) {
return Type::NonInternal();
}
Type Typer::Visitor::TypeJSLoadGlobal(Node* node) {
return Type::NonInternal();
}
......
......@@ -722,6 +722,9 @@ void Verifier::Visitor::Check(Node* node, const AllNodes& all) {
case IrOpcode::kJSLoadNamed:
CheckTypeIs(node, Type::Any());
break;
case IrOpcode::kJSLoadNamedFromSuper:
CheckTypeIs(node, Type::Any());
break;
case IrOpcode::kJSLoadGlobal:
CheckTypeIs(node, Type::Any());
CHECK(LoadGlobalParametersOf(node->op()).feedback().IsValid());
......
......@@ -1291,6 +1291,8 @@ DEFINE_INT(max_valid_polymorphic_map_count, 4,
DEFINE_BOOL(native_code_counters, DEBUG_BOOL,
"generate extra code for manipulating stats counters")
DEFINE_BOOL(super_ic, false, "use an IC for super property loads")
// objects.cc
DEFINE_BOOL(thin_strings, true, "Enable ThinString support")
DEFINE_BOOL(trace_prototype_users, false,
......
......@@ -830,6 +830,13 @@ BytecodeArrayBuilder& BytecodeArrayBuilder::LoadNamedProperty(
return *this;
}
BytecodeArrayBuilder& BytecodeArrayBuilder::LoadNamedPropertyFromSuper(
Register object, const AstRawString* name) {
size_t name_index = GetConstantPoolEntry(name);
OutputLdaNamedPropertyFromSuper(object, name_index);
return *this;
}
BytecodeArrayBuilder& BytecodeArrayBuilder::LoadNamedPropertyNoFeedback(
Register object, const AstRawString* name) {
size_t name_index = GetConstantPoolEntry(name);
......
......@@ -136,6 +136,9 @@ class V8_EXPORT_PRIVATE BytecodeArrayBuilder final {
BytecodeArrayBuilder& LoadNamedPropertyNoFeedback(Register object,
const AstRawString* name);
BytecodeArrayBuilder& LoadNamedPropertyFromSuper(Register object,
const AstRawString* name);
// Keyed load property. The key should be in the accumulator.
BytecodeArrayBuilder& LoadKeyedProperty(Register object, int feedback_slot);
......
......@@ -4718,19 +4718,32 @@ void BytecodeGenerator::VisitNamedSuperPropertyLoad(Property* property,
RegisterAllocationScope register_scope(this);
SuperPropertyReference* super_property =
property->obj()->AsSuperPropertyReference();
RegisterList args = register_allocator()->NewRegisterList(3);
BuildThisVariableLoad();
builder()->StoreAccumulatorInRegister(args[0]);
VisitForRegisterValue(super_property->home_object(), args[1]);
if (FLAG_super_ic) {
Register receiver = register_allocator()->NewRegister();
BuildThisVariableLoad();
builder()->StoreAccumulatorInRegister(receiver);
VisitForAccumulatorValue(super_property->home_object());
builder()->SetExpressionPosition(property);
builder()->LoadNamedPropertyFromSuper(
receiver, property->key()->AsLiteral()->AsRawPropertyName());
if (opt_receiver_out.is_valid()) {
builder()->MoveRegister(receiver, opt_receiver_out);
}
} else {
RegisterList args = register_allocator()->NewRegisterList(3);
BuildThisVariableLoad();
builder()->StoreAccumulatorInRegister(args[0]);
VisitForRegisterValue(super_property->home_object(), args[1]);
builder()->SetExpressionPosition(property);
builder()
->LoadLiteral(property->key()->AsLiteral()->AsRawPropertyName())
.StoreAccumulatorInRegister(args[2])
.CallRuntime(Runtime::kLoadFromSuper, args);
builder()->SetExpressionPosition(property);
builder()
->LoadLiteral(property->key()->AsLiteral()->AsRawPropertyName())
.StoreAccumulatorInRegister(args[2])
.CallRuntime(Runtime::kLoadFromSuper, args);
if (opt_receiver_out.is_valid()) {
builder()->MoveRegister(args[0], opt_receiver_out);
if (opt_receiver_out.is_valid()) {
builder()->MoveRegister(args[0], opt_receiver_out);
}
}
}
......
......@@ -100,6 +100,8 @@ namespace interpreter {
OperandType::kIdx, OperandType::kIdx) \
V(LdaNamedPropertyNoFeedback, AccumulatorUse::kWrite, OperandType::kReg, \
OperandType::kIdx) \
V(LdaNamedPropertyFromSuper, AccumulatorUse::kReadWrite, OperandType::kReg, \
OperandType::kIdx) \
V(LdaKeyedProperty, AccumulatorUse::kReadWrite, OperandType::kReg, \
OperandType::kIdx) \
\
......
......@@ -539,9 +539,10 @@ IGNITION_HANDLER(LdaNamedProperty, InterpreterAssembler) {
}
}
// LdaNamedPropertyNoFeedback <object> <name>
// LdaNamedPropertyNoFeedback <object> <name_index>
//
// Calls the GetProperty builtin for <object> and the key <name>.
// Calls the GetProperty builtin for <object> and the name at
// constant pool entry <name_index>.
IGNITION_HANDLER(LdaNamedPropertyNoFeedback, InterpreterAssembler) {
TNode<Object> object = LoadRegisterAtOperandIndex(0);
TNode<Name> name = CAST(LoadConstantPoolEntryAtOperandIndex(1));
......@@ -552,6 +553,22 @@ IGNITION_HANDLER(LdaNamedPropertyNoFeedback, InterpreterAssembler) {
Dispatch();
}
// LdaNamedPropertyFromSuper <receiver> <name_index>
//
// Calls the LoadFromSuper runtime function for <receiver>, home object (in the
// accumulator) and the name at constant pool entry <name_index>.
IGNITION_HANDLER(LdaNamedPropertyFromSuper, InterpreterAssembler) {
TNode<Object> receiver = LoadRegisterAtOperandIndex(0);
TNode<Object> home_object = GetAccumulator();
TNode<Object> name = LoadConstantPoolEntryAtOperandIndex(1);
TNode<Context> context = GetContext();
TNode<Object> result = CallRuntime(Runtime::kLoadFromSuper, context, receiver,
home_object, name);
SetAccumulator(result);
Dispatch();
}
// LdaKeyedProperty <object> <slot>
//
// Calls the KeyedLoadIC at FeedBackVector slot <slot> for <object> and the key
......
......@@ -137,6 +137,7 @@ TEST_F(BytecodeArrayBuilderTest, AllBytecodesGenerated) {
// Emit load / store property operations.
builder.LoadNamedProperty(reg, name, load_slot.ToInt())
.LoadNamedPropertyNoFeedback(reg, name)
.LoadNamedPropertyFromSuper(reg, name)
.LoadKeyedProperty(reg, keyed_load_slot.ToInt())
.StoreNamedProperty(reg, name, sloppy_store_slot.ToInt(),
LanguageMode::kSloppy)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment