[turbofan] Avoid embedding type feedback vector into code.
R=bmeurer@chromium.org Review URL: https://codereview.chromium.org/1198263004 Cr-Commit-Position: refs/heads/master@{#29216}
This commit is contained in:
parent
6c6a238004
commit
4ab2a18094
@ -483,16 +483,6 @@ Node* AstGraphBuilder::GetFunctionClosure() {
|
||||
}
|
||||
|
||||
|
||||
Node* AstGraphBuilder::GetFeedbackVector() {
|
||||
if (!feedback_vector_.is_set()) {
|
||||
Node* vector =
|
||||
jsgraph()->Constant(handle(info()->shared_info()->feedback_vector()));
|
||||
feedback_vector_.set(vector);
|
||||
}
|
||||
return feedback_vector_.get();
|
||||
}
|
||||
|
||||
|
||||
void AstGraphBuilder::CreateFunctionContext(bool constant_context) {
|
||||
function_context_.set(constant_context
|
||||
? jsgraph()->HeapConstant(info()->context())
|
||||
@ -3297,7 +3287,7 @@ Node* AstGraphBuilder::BuildVariableLoad(Variable* variable,
|
||||
uint32_t check_bitset = ComputeBitsetForDynamicGlobal(variable);
|
||||
const Operator* op = javascript()->LoadDynamicGlobal(
|
||||
name, check_bitset, feedback, contextual_mode);
|
||||
value = NewNode(op, GetFeedbackVector(), current_context());
|
||||
value = NewNode(op, BuildLoadFeedbackVector(), current_context());
|
||||
states.AddToNode(value, bailout_id, combine);
|
||||
} else if (mode == DYNAMIC_LOCAL) {
|
||||
Variable* local = variable->local_if_not_shadowed();
|
||||
@ -3321,7 +3311,7 @@ Node* AstGraphBuilder::BuildVariableLoad(Variable* variable,
|
||||
uint32_t check_bitset = DynamicGlobalAccess::kFullCheckRequired;
|
||||
const Operator* op = javascript()->LoadDynamicGlobal(
|
||||
name, check_bitset, feedback, contextual_mode);
|
||||
value = NewNode(op, GetFeedbackVector(), current_context());
|
||||
value = NewNode(op, BuildLoadFeedbackVector(), current_context());
|
||||
states.AddToNode(value, bailout_id, combine);
|
||||
}
|
||||
return value;
|
||||
@ -3495,8 +3485,8 @@ static inline Node* Record(JSTypeFeedbackTable* js_type_feedback, Node* node,
|
||||
Node* AstGraphBuilder::BuildKeyedLoad(Node* object, Node* key,
|
||||
const VectorSlotPair& feedback) {
|
||||
const Operator* op = javascript()->LoadProperty(feedback);
|
||||
return Record(js_type_feedback_,
|
||||
NewNode(op, object, key, GetFeedbackVector()), feedback.slot());
|
||||
Node* node = NewNode(op, object, key, BuildLoadFeedbackVector());
|
||||
return Record(js_type_feedback_, node, feedback.slot());
|
||||
}
|
||||
|
||||
|
||||
@ -3505,8 +3495,8 @@ Node* AstGraphBuilder::BuildNamedLoad(Node* object, Handle<Name> name,
|
||||
ContextualMode mode) {
|
||||
const Operator* op =
|
||||
javascript()->LoadNamed(MakeUnique(name), feedback, mode);
|
||||
return Record(js_type_feedback_, NewNode(op, object, GetFeedbackVector()),
|
||||
feedback.slot());
|
||||
Node* node = NewNode(op, object, BuildLoadFeedbackVector());
|
||||
return Record(js_type_feedback_, node, feedback.slot());
|
||||
}
|
||||
|
||||
|
||||
@ -3514,7 +3504,8 @@ Node* AstGraphBuilder::BuildKeyedStore(Node* object, Node* key, Node* value,
|
||||
const VectorSlotPair& feedback,
|
||||
TypeFeedbackId id) {
|
||||
const Operator* op = javascript()->StoreProperty(language_mode(), feedback);
|
||||
return Record(js_type_feedback_, NewNode(op, object, key, value), id);
|
||||
Node* node = NewNode(op, object, key, value);
|
||||
return Record(js_type_feedback_, node, id);
|
||||
}
|
||||
|
||||
|
||||
@ -3524,7 +3515,8 @@ Node* AstGraphBuilder::BuildNamedStore(Node* object, Handle<Name> name,
|
||||
TypeFeedbackId id) {
|
||||
const Operator* op =
|
||||
javascript()->StoreNamed(language_mode(), MakeUnique(name), feedback);
|
||||
return Record(js_type_feedback_, NewNode(op, object, value), id);
|
||||
Node* node = NewNode(op, object, value);
|
||||
return Record(js_type_feedback_, node, id);
|
||||
}
|
||||
|
||||
|
||||
@ -3533,8 +3525,8 @@ Node* AstGraphBuilder::BuildNamedSuperLoad(Node* receiver, Node* home_object,
|
||||
const VectorSlotPair& feedback) {
|
||||
Node* name_node = jsgraph()->Constant(name);
|
||||
const Operator* op = javascript()->CallRuntime(Runtime::kLoadFromSuper, 3);
|
||||
Node* value = NewNode(op, receiver, home_object, name_node);
|
||||
return Record(js_type_feedback_, value, feedback.slot());
|
||||
Node* node = NewNode(op, receiver, home_object, name_node);
|
||||
return Record(js_type_feedback_, node, feedback.slot());
|
||||
}
|
||||
|
||||
|
||||
@ -3543,8 +3535,8 @@ Node* AstGraphBuilder::BuildKeyedSuperLoad(Node* receiver, Node* home_object,
|
||||
const VectorSlotPair& feedback) {
|
||||
const Operator* op =
|
||||
javascript()->CallRuntime(Runtime::kLoadKeyedFromSuper, 3);
|
||||
Node* value = NewNode(op, receiver, home_object, key);
|
||||
return Record(js_type_feedback_, value, feedback.slot());
|
||||
Node* node = NewNode(op, receiver, home_object, key);
|
||||
return Record(js_type_feedback_, node, feedback.slot());
|
||||
}
|
||||
|
||||
|
||||
@ -3555,8 +3547,8 @@ Node* AstGraphBuilder::BuildKeyedSuperStore(Node* receiver, Node* home_object,
|
||||
? Runtime::kStoreKeyedToSuper_Strict
|
||||
: Runtime::kStoreKeyedToSuper_Sloppy;
|
||||
const Operator* op = javascript()->CallRuntime(function_id, 4);
|
||||
Node* result = NewNode(op, receiver, home_object, key, value);
|
||||
return Record(js_type_feedback_, result, id);
|
||||
Node* node = NewNode(op, receiver, home_object, key, value);
|
||||
return Record(js_type_feedback_, node, id);
|
||||
}
|
||||
|
||||
|
||||
@ -3568,8 +3560,8 @@ Node* AstGraphBuilder::BuildNamedSuperStore(Node* receiver, Node* home_object,
|
||||
? Runtime::kStoreToSuper_Strict
|
||||
: Runtime::kStoreToSuper_Sloppy;
|
||||
const Operator* op = javascript()->CallRuntime(function_id, 4);
|
||||
Node* result = NewNode(op, receiver, home_object, name_node, value);
|
||||
return Record(js_type_feedback_, result, id);
|
||||
Node* node = NewNode(op, receiver, home_object, name_node, value);
|
||||
return Record(js_type_feedback_, node, id);
|
||||
}
|
||||
|
||||
|
||||
@ -3579,6 +3571,13 @@ Node* AstGraphBuilder::BuildLoadObjectField(Node* object, int offset) {
|
||||
}
|
||||
|
||||
|
||||
Node* AstGraphBuilder::BuildLoadImmutableObjectField(Node* object, int offset) {
|
||||
return graph()->NewNode(jsgraph()->machine()->Load(kMachAnyTagged), object,
|
||||
jsgraph()->IntPtrConstant(offset - kHeapObjectTag),
|
||||
graph()->start(), graph()->start());
|
||||
}
|
||||
|
||||
|
||||
Node* AstGraphBuilder::BuildLoadBuiltinsObject() {
|
||||
Node* global = BuildLoadGlobalObject();
|
||||
Node* builtins =
|
||||
@ -3602,6 +3601,19 @@ Node* AstGraphBuilder::BuildLoadGlobalProxy() {
|
||||
}
|
||||
|
||||
|
||||
Node* AstGraphBuilder::BuildLoadFeedbackVector() {
|
||||
if (!feedback_vector_.is_set()) {
|
||||
Node* closure = GetFunctionClosure();
|
||||
Node* shared = BuildLoadImmutableObjectField(
|
||||
closure, JSFunction::kSharedFunctionInfoOffset);
|
||||
Node* vector = BuildLoadImmutableObjectField(
|
||||
shared, SharedFunctionInfo::kFeedbackVectorOffset);
|
||||
feedback_vector_.set(vector);
|
||||
}
|
||||
return feedback_vector_.get();
|
||||
}
|
||||
|
||||
|
||||
Node* AstGraphBuilder::BuildLoadExternal(ExternalReference reference,
|
||||
MachineType type) {
|
||||
return NewNode(jsgraph()->machine()->Load(type),
|
||||
|
@ -88,7 +88,6 @@ class AstGraphBuilder : public AstVisitor {
|
||||
// Nodes representing values in the activation record.
|
||||
SetOncePointer<Node> function_closure_;
|
||||
SetOncePointer<Node> function_context_;
|
||||
SetOncePointer<Node> feedback_vector_;
|
||||
|
||||
// Tracks how many try-blocks are currently entered.
|
||||
int try_catch_nesting_level_;
|
||||
@ -98,6 +97,9 @@ class AstGraphBuilder : public AstVisitor {
|
||||
int input_buffer_size_;
|
||||
Node** input_buffer_;
|
||||
|
||||
// Optimization to cache loaded feedback vector.
|
||||
SetOncePointer<Node> feedback_vector_;
|
||||
|
||||
// Control nodes that exit the function body.
|
||||
ZoneVector<Node*> exit_controls_;
|
||||
|
||||
@ -155,9 +157,6 @@ class AstGraphBuilder : public AstVisitor {
|
||||
Node* GetFunctionClosureForContext();
|
||||
Node* GetFunctionClosure();
|
||||
|
||||
// Get or create the node that represents the functions type feedback vector.
|
||||
Node* GetFeedbackVector();
|
||||
|
||||
// Node creation helpers.
|
||||
Node* NewNode(const Operator* op, bool incomplete = false) {
|
||||
return MakeNode(op, 0, static_cast<Node**>(NULL), incomplete);
|
||||
@ -312,8 +311,11 @@ class AstGraphBuilder : public AstVisitor {
|
||||
Node* BuildLoadBuiltinsObject();
|
||||
Node* BuildLoadGlobalObject();
|
||||
Node* BuildLoadGlobalProxy();
|
||||
Node* BuildLoadClosure();
|
||||
Node* BuildLoadFeedbackVector();
|
||||
|
||||
// Builder for accessing a (potentially immutable) object field.
|
||||
Node* BuildLoadObjectField(Node* object, int offset);
|
||||
Node* BuildLoadImmutableObjectField(Node* object, int offset);
|
||||
|
||||
// Builders for accessing external references.
|
||||
Node* BuildLoadExternal(ExternalReference ref, MachineType type);
|
||||
|
@ -242,6 +242,7 @@ TEST(ContextLoadedFromActivation) {
|
||||
i::Handle<i::Object> ofun = v8::Utils::OpenHandle(*value);
|
||||
i::Handle<i::JSFunction> jsfun = Handle<JSFunction>::cast(ofun);
|
||||
jsfun->set_code(T.function->code());
|
||||
jsfun->set_shared(T.function->shared());
|
||||
context->Global()->Set(v8_str("foo"), v8::Utils::ToLocal(jsfun));
|
||||
CompileRun("var x = 24;");
|
||||
ExpectInt32("foo();", 24);
|
||||
@ -263,6 +264,7 @@ TEST(BuiltinLoadedFromActivation) {
|
||||
i::Handle<i::Object> ofun = v8::Utils::OpenHandle(*value);
|
||||
i::Handle<i::JSFunction> jsfun = Handle<JSFunction>::cast(ofun);
|
||||
jsfun->set_code(T.function->code());
|
||||
jsfun->set_shared(T.function->shared());
|
||||
context->Global()->Set(v8_str("foo"), v8::Utils::ToLocal(jsfun));
|
||||
CompileRun("var x = 24;");
|
||||
ExpectObject("foo()", context->Global());
|
||||
|
Loading…
Reference in New Issue
Block a user