summaryrefslogtreecommitdiff
path: root/deps/v8/src/compiler/ast-graph-builder.cc
diff options
context:
space:
mode:
Diffstat (limited to 'deps/v8/src/compiler/ast-graph-builder.cc')
-rw-r--r--deps/v8/src/compiler/ast-graph-builder.cc256
1 files changed, 131 insertions, 125 deletions
diff --git a/deps/v8/src/compiler/ast-graph-builder.cc b/deps/v8/src/compiler/ast-graph-builder.cc
index 0f1fb291eb..b292a2e49e 100644
--- a/deps/v8/src/compiler/ast-graph-builder.cc
+++ b/deps/v8/src/compiler/ast-graph-builder.cc
@@ -4,7 +4,9 @@
#include "src/compiler/ast-graph-builder.h"
+#include "src/ast/compile-time-value.h"
#include "src/ast/scopes.h"
+#include "src/compilation-info.h"
#include "src/compiler.h"
#include "src/compiler/ast-loop-assignment-analyzer.h"
#include "src/compiler/control-builders.h"
@@ -16,7 +18,6 @@
#include "src/compiler/operator-properties.h"
#include "src/compiler/state-values-utils.h"
#include "src/compiler/type-hint-analyzer.h"
-#include "src/parsing/parser.h"
namespace v8 {
namespace internal {
@@ -410,14 +411,15 @@ class AstGraphBuilder::ControlScopeForFinally : public ControlScope {
TryFinallyBuilder* control_;
};
-
AstGraphBuilder::AstGraphBuilder(Zone* local_zone, CompilationInfo* info,
- JSGraph* jsgraph, LoopAssignmentAnalysis* loop,
+ JSGraph* jsgraph, float invocation_frequency,
+ LoopAssignmentAnalysis* loop,
TypeHintAnalysis* type_hint_analysis)
: isolate_(info->isolate()),
local_zone_(local_zone),
info_(info),
jsgraph_(jsgraph),
+ invocation_frequency_(invocation_frequency),
environment_(nullptr),
ast_context_(nullptr),
globals_(0, local_zone),
@@ -535,12 +537,11 @@ bool AstGraphBuilder::CreateGraph(bool stack_check) {
// TODO(mstarzinger): For now we cannot assume that the {this} parameter is
// not {the_hole}, because for derived classes {this} has a TDZ and the
// JSConstructStubForDerived magically passes {the_hole} as a receiver.
- if (scope->has_this_declaration() && scope->receiver()->is_const_mode()) {
+ if (scope->has_this_declaration() && scope->receiver()->mode() == CONST) {
env.RawParameterBind(0, jsgraph()->TheHoleConstant());
}
- // Build local context only if there are context allocated variables.
- if (scope->num_heap_slots() > 0) {
+ if (scope->NeedsContext()) {
// Push a new inner context scope for the current activation.
Node* inner_context = BuildLocalActivationContext(GetFunctionContext());
ContextScope top_context(this, scope, inner_context);
@@ -573,9 +574,8 @@ void AstGraphBuilder::CreateGraphBody(bool stack_check) {
BuildArgumentsObject(scope->arguments());
// Build rest arguments array if it is used.
- int rest_index;
- Variable* rest_parameter = scope->rest_parameter(&rest_index);
- BuildRestArgumentsArray(rest_parameter, rest_index);
+ Variable* rest_parameter = scope->rest_parameter();
+ BuildRestArgumentsArray(rest_parameter);
// Build assignment to {.this_function} variable if it is used.
BuildThisFunctionVariable(scope->this_function_var());
@@ -629,8 +629,7 @@ void AstGraphBuilder::ClearNonLiveSlotsInFrameStates() {
// Gets the bailout id just before reading a variable proxy, but only for
// unallocated variables.
static BailoutId BeforeId(VariableProxy* proxy) {
- return proxy->var()->IsUnallocatedOrGlobalSlot() ? proxy->BeforeId()
- : BailoutId::None();
+ return proxy->var()->IsUnallocated() ? proxy->BeforeId() : BailoutId::None();
}
static const char* GetDebugParameterName(Zone* zone, DeclarationScope* scope,
@@ -788,6 +787,10 @@ AstGraphBuilder::Environment::CopyAsUnreachable() {
return env;
}
+AstGraphBuilder::Environment* AstGraphBuilder::Environment::CopyForOsrEntry() {
+ return new (zone())
+ Environment(this, builder_->liveness_analyzer()->NewBlock());
+}
AstGraphBuilder::Environment*
AstGraphBuilder::Environment::CopyAndShareLiveness() {
@@ -802,8 +805,15 @@ AstGraphBuilder::Environment::CopyAndShareLiveness() {
AstGraphBuilder::Environment* AstGraphBuilder::Environment::CopyForLoop(
BitVector* assigned, bool is_osr) {
- PrepareForLoop(assigned, is_osr);
- return CopyAndShareLiveness();
+ PrepareForLoop(assigned);
+ Environment* loop = CopyAndShareLiveness();
+ if (is_osr) {
+ // Create and merge the OSR entry if necessary.
+ Environment* osr_env = CopyForOsrEntry();
+ osr_env->PrepareForOsrEntry();
+ loop->Merge(osr_env);
+ }
+ return loop;
}
@@ -1085,7 +1095,6 @@ void AstGraphBuilder::Visit(Expression* expr) {
void AstGraphBuilder::VisitVariableDeclaration(VariableDeclaration* decl) {
Variable* variable = decl->proxy()->var();
switch (variable->location()) {
- case VariableLocation::GLOBAL:
case VariableLocation::UNALLOCATED: {
DCHECK(!variable->binding_needs_init());
FeedbackVectorSlot slot = decl->proxy()->VariableFeedbackSlot();
@@ -1125,7 +1134,6 @@ void AstGraphBuilder::VisitVariableDeclaration(VariableDeclaration* decl) {
void AstGraphBuilder::VisitFunctionDeclaration(FunctionDeclaration* decl) {
Variable* variable = decl->proxy()->var();
switch (variable->location()) {
- case VariableLocation::GLOBAL:
case VariableLocation::UNALLOCATED: {
Handle<SharedFunctionInfo> function = Compiler::GetSharedFunctionInfo(
decl->fun(), info()->script(), info());
@@ -1240,7 +1248,8 @@ void AstGraphBuilder::VisitWithStatement(WithStatement* stmt) {
VisitForValue(stmt->expression());
Node* value = environment()->Pop();
Node* object = BuildToObject(value, stmt->ToObjectId());
- const Operator* op = javascript()->CreateWithContext();
+ Handle<ScopeInfo> scope_info = stmt->scope()->scope_info();
+ const Operator* op = javascript()->CreateWithContext(scope_info);
Node* context = NewNode(op, object, GetFunctionClosureForContext());
PrepareFrameState(context, stmt->EntryId());
VisitInScope(stmt->statement(), stmt->scope(), context);
@@ -1394,9 +1403,14 @@ void AstGraphBuilder::VisitForInStatement(ForInStatement* stmt) {
Node* cache_type = environment()->Peek(3);
Node* object = environment()->Peek(4);
- // Check loop termination condition.
- Node* exit_cond = NewNode(javascript()->ForInDone(), index, cache_length);
- for_loop.BreakWhen(exit_cond);
+ // Check loop termination condition (we know that the {index} is always
+ // in Smi range, so we can just set the hint on the comparison below).
+ PrepareEagerCheckpoint(stmt->EntryId());
+ Node* exit_cond =
+ NewNode(javascript()->LessThan(CompareOperationHint::kSignedSmall),
+ index, cache_length);
+ PrepareFrameState(exit_cond, BailoutId::None());
+ for_loop.BreakUnless(exit_cond);
// Compute the next enumerated value.
Node* value = NewNode(javascript()->ForInNext(), object, cache_array,
@@ -1424,9 +1438,13 @@ void AstGraphBuilder::VisitForInStatement(ForInStatement* stmt) {
test_value.End();
for_loop.EndBody();
- // Increment counter and continue.
+ // Increment counter and continue (we know that the {index} is always
+ // in Smi range, so we can just set the hint on the increment below).
index = environment()->Peek(0);
- index = NewNode(javascript()->ForInStep(), index);
+ PrepareEagerCheckpoint(stmt->IncrementId());
+ index = NewNode(javascript()->Add(BinaryOperationHint::kSignedSmall),
+ index, jsgraph()->OneConstant());
+ PrepareFrameState(index, BailoutId::None());
environment()->Poke(0, index);
}
for_loop.EndLoop();
@@ -1475,7 +1493,8 @@ void AstGraphBuilder::VisitTryCatchStatement(TryCatchStatement* stmt) {
// Create a catch scope that binds the exception.
Node* exception = try_control.GetExceptionNode();
Handle<String> name = stmt->variable()->name();
- const Operator* op = javascript()->CreateCatchContext(name);
+ Handle<ScopeInfo> scope_info = stmt->scope()->scope_info();
+ const Operator* op = javascript()->CreateCatchContext(name, scope_info);
Node* context = NewNode(op, exception, GetFunctionClosureForContext());
// Evaluate the catch-block.
@@ -1595,7 +1614,7 @@ void AstGraphBuilder::VisitClassLiteral(ClassLiteral* expr) {
// Create nodes to store method values into the literal.
for (int i = 0; i < expr->properties()->length(); i++) {
- ObjectLiteral::Property* property = expr->properties()->at(i);
+ ClassLiteral::Property* property = expr->properties()->at(i);
environment()->Push(environment()->Peek(property->is_static() ? 1 : 0));
VisitForValue(property->key());
@@ -1620,11 +1639,7 @@ void AstGraphBuilder::VisitClassLiteral(ClassLiteral* expr) {
BuildSetHomeObject(value, receiver, property);
switch (property->kind()) {
- case ObjectLiteral::Property::CONSTANT:
- case ObjectLiteral::Property::MATERIALIZED_LITERAL:
- case ObjectLiteral::Property::PROTOTYPE:
- UNREACHABLE();
- case ObjectLiteral::Property::COMPUTED: {
+ case ClassLiteral::Property::METHOD: {
Node* attr = jsgraph()->Constant(DONT_ENUM);
Node* set_function_name =
jsgraph()->Constant(property->NeedsSetFunctionName());
@@ -1634,20 +1649,24 @@ void AstGraphBuilder::VisitClassLiteral(ClassLiteral* expr) {
PrepareFrameState(call, BailoutId::None());
break;
}
- case ObjectLiteral::Property::GETTER: {
+ case ClassLiteral::Property::GETTER: {
Node* attr = jsgraph()->Constant(DONT_ENUM);
const Operator* op = javascript()->CallRuntime(
Runtime::kDefineGetterPropertyUnchecked, 4);
NewNode(op, receiver, key, value, attr);
break;
}
- case ObjectLiteral::Property::SETTER: {
+ case ClassLiteral::Property::SETTER: {
Node* attr = jsgraph()->Constant(DONT_ENUM);
const Operator* op = javascript()->CallRuntime(
Runtime::kDefineSetterPropertyUnchecked, 4);
NewNode(op, receiver, key, value, attr);
break;
}
+ case ClassLiteral::Property::FIELD: {
+ UNREACHABLE();
+ break;
+ }
}
}
@@ -1945,8 +1964,8 @@ void AstGraphBuilder::VisitArrayLiteral(ArrayLiteral* expr) {
// Create nodes to evaluate all the non-constant subexpressions and to store
// them into the newly cloned array.
- int array_index = 0;
- for (; array_index < expr->values()->length(); array_index++) {
+ for (int array_index = 0; array_index < expr->values()->length();
+ array_index++) {
Expression* subexpr = expr->values()->at(array_index);
DCHECK(!subexpr->IsSpread());
if (CompileTimeValue::IsCompileTimeValue(subexpr)) continue;
@@ -1961,26 +1980,6 @@ void AstGraphBuilder::VisitArrayLiteral(ArrayLiteral* expr) {
OutputFrameStateCombine::Ignore());
}
- // In case the array literal contains spread expressions it has two parts. The
- // first part is the "static" array which has a literal index is handled
- // above. The second part is the part after the first spread expression
- // (inclusive) and these elements gets appended to the array. Note that the
- // number elements an iterable produces is unknown ahead of time.
- for (; array_index < expr->values()->length(); array_index++) {
- Expression* subexpr = expr->values()->at(array_index);
- DCHECK(!subexpr->IsSpread());
-
- VisitForValue(subexpr);
- {
- Node* value = environment()->Pop();
- Node* array = environment()->Pop();
- const Operator* op = javascript()->CallRuntime(Runtime::kAppendElement);
- Node* result = NewNode(op, array, value);
- PrepareFrameState(result, expr->GetIdForElement(array_index));
- environment()->Push(result);
- }
- }
-
ast_context()->ProduceValue(expr, environment()->Pop());
}
@@ -2447,12 +2446,17 @@ void AstGraphBuilder::VisitCall(Call* expr) {
}
// Create node to perform the function call.
+ float const frequency = ComputeCallFrequency(expr->CallFeedbackICSlot());
VectorSlotPair feedback = CreateVectorSlotPair(expr->CallFeedbackICSlot());
- const Operator* call = javascript()->CallFunction(
- args->length() + 2, feedback, receiver_hint, expr->tail_call_mode());
+ const Operator* call =
+ javascript()->CallFunction(args->length() + 2, frequency, feedback,
+ receiver_hint, expr->tail_call_mode());
PrepareEagerCheckpoint(possibly_eval ? expr->EvalId() : expr->CallId());
Node* value = ProcessArguments(call, args->length() + 2);
- environment()->Push(value->InputAt(0)); // The callee passed to the call.
+ // The callee passed to the call, we just need to push something here to
+ // satisfy the bailout location contract. The fullcodegen code will not
+ // ever look at this value, so we just push optimized_out here.
+ environment()->Push(jsgraph()->OptimizedOutConstant());
PrepareFrameState(value, expr->ReturnId(), OutputFrameStateCombine::Push());
environment()->Drop(1);
ast_context()->ProduceValue(expr, value);
@@ -2480,7 +2484,7 @@ void AstGraphBuilder::VisitCallSuper(Call* expr) {
// Create node to perform the super call.
const Operator* call =
- javascript()->CallConstruct(args->length() + 2, VectorSlotPair());
+ javascript()->CallConstruct(args->length() + 2, 0.0f, VectorSlotPair());
Node* value = ProcessArguments(call, args->length() + 2);
PrepareFrameState(value, expr->ReturnId(), OutputFrameStateCombine::Push());
ast_context()->ProduceValue(expr, value);
@@ -2498,9 +2502,10 @@ void AstGraphBuilder::VisitCallNew(CallNew* expr) {
environment()->Push(environment()->Peek(args->length()));
// Create node to perform the construct call.
+ float const frequency = ComputeCallFrequency(expr->CallNewFeedbackSlot());
VectorSlotPair feedback = CreateVectorSlotPair(expr->CallNewFeedbackSlot());
const Operator* call =
- javascript()->CallConstruct(args->length() + 2, feedback);
+ javascript()->CallConstruct(args->length() + 2, frequency, feedback);
Node* value = ProcessArguments(call, args->length() + 2);
PrepareFrameState(value, expr->ReturnId(), OutputFrameStateCombine::Push());
ast_context()->ProduceValue(expr, value);
@@ -3086,7 +3091,7 @@ uint32_t AstGraphBuilder::ComputeBitsetForDynamicGlobal(Variable* variable) {
DCHECK_EQ(DYNAMIC_GLOBAL, variable->mode());
uint32_t check_depths = 0;
for (Scope* s = current_scope(); s != nullptr; s = s->outer_scope()) {
- if (s->num_heap_slots() <= 0) continue;
+ if (!s->NeedsContext()) continue;
if (!s->calls_sloppy_eval()) continue;
int depth = current_scope()->ContextChainLength(s);
if (depth > kMaxCheckDepth) return kFullCheckRequired;
@@ -3100,7 +3105,7 @@ uint32_t AstGraphBuilder::ComputeBitsetForDynamicContext(Variable* variable) {
DCHECK_EQ(DYNAMIC_LOCAL, variable->mode());
uint32_t check_depths = 0;
for (Scope* s = current_scope(); s != nullptr; s = s->outer_scope()) {
- if (s->num_heap_slots() <= 0) continue;
+ if (!s->NeedsContext()) continue;
if (!s->calls_sloppy_eval() && s != variable->scope()) continue;
int depth = current_scope()->ContextChainLength(s);
if (depth > kMaxCheckDepth) return kFullCheckRequired;
@@ -3110,6 +3115,13 @@ uint32_t AstGraphBuilder::ComputeBitsetForDynamicContext(Variable* variable) {
return check_depths;
}
+float AstGraphBuilder::ComputeCallFrequency(FeedbackVectorSlot slot) const {
+ if (slot.IsInvalid()) return 0.0f;
+ Handle<TypeFeedbackVector> feedback_vector(
+ info()->closure()->feedback_vector(), isolate());
+ CallICNexus nexus(feedback_vector, slot);
+ return nexus.ComputeCallFrequency() * invocation_frequency_;
+}
Node* AstGraphBuilder::ProcessArguments(const Operator* op, int arity) {
DCHECK(environment()->stack_height() >= arity);
@@ -3171,7 +3183,7 @@ Node* AstGraphBuilder::BuildLocalScriptContext(Scope* scope) {
DCHECK(scope->is_script_scope());
// Allocate a new local context.
- Handle<ScopeInfo> scope_info = scope->GetScopeInfo(isolate());
+ Handle<ScopeInfo> scope_info = scope->scope_info();
const Operator* op = javascript()->CreateScriptContext(scope_info);
Node* local_context = NewNode(op, GetFunctionClosure());
PrepareFrameState(local_context, BailoutId::ScriptContext(),
@@ -3185,7 +3197,7 @@ Node* AstGraphBuilder::BuildLocalBlockContext(Scope* scope) {
DCHECK(scope->is_block_scope());
// Allocate a new local context.
- Handle<ScopeInfo> scope_info = scope->GetScopeInfo(isolate());
+ Handle<ScopeInfo> scope_info = scope->scope_info();
const Operator* op = javascript()->CreateBlockContext(scope_info);
Node* local_context = NewNode(op, GetFunctionClosureForContext());
@@ -3213,8 +3225,7 @@ Node* AstGraphBuilder::BuildArgumentsObject(Variable* arguments) {
return object;
}
-
-Node* AstGraphBuilder::BuildRestArgumentsArray(Variable* rest, int index) {
+Node* AstGraphBuilder::BuildRestArgumentsArray(Variable* rest) {
if (rest == nullptr) return nullptr;
// Allocate and initialize a new arguments object.
@@ -3321,7 +3332,6 @@ Node* AstGraphBuilder::BuildVariableLoad(Variable* variable,
TypeofMode typeof_mode) {
Node* the_hole = jsgraph()->TheHoleConstant();
switch (variable->location()) {
- case VariableLocation::GLOBAL:
case VariableLocation::UNALLOCATED: {
// Global var, const, or let variable.
Handle<Name> name = variable->name();
@@ -3383,7 +3393,6 @@ Node* AstGraphBuilder::BuildVariableDelete(Variable* variable,
BailoutId bailout_id,
OutputFrameStateCombine combine) {
switch (variable->location()) {
- case VariableLocation::GLOBAL:
case VariableLocation::UNALLOCATED: {
// Global var, const, or let variable.
Node* global = BuildLoadGlobalObject();
@@ -3422,7 +3431,6 @@ Node* AstGraphBuilder::BuildVariableAssignment(
Node* the_hole = jsgraph()->TheHoleConstant();
VariableMode mode = variable->mode();
switch (variable->location()) {
- case VariableLocation::GLOBAL:
case VariableLocation::UNALLOCATED: {
// Global var, const, or let variable.
Handle<Name> name = variable->name();
@@ -3433,15 +3441,7 @@ Node* AstGraphBuilder::BuildVariableAssignment(
case VariableLocation::PARAMETER:
case VariableLocation::LOCAL:
// Local var, const, or let variable.
- if (mode == CONST_LEGACY && op != Token::INIT) {
- // Non-initializing assignment to legacy const is
- // - exception in strict mode.
- // - ignored in sloppy mode.
- if (is_strict(language_mode())) {
- return BuildThrowConstAssignError(bailout_id);
- }
- return value;
- } else if (mode == LET && op == Token::INIT) {
+ if (mode == LET && op == Token::INIT) {
// No initialization check needed because scoping guarantees it. Note
// that we still perform a lookup to keep the variable live, because
// baseline code might contain debug code that inspects the variable.
@@ -3464,6 +3464,16 @@ Node* AstGraphBuilder::BuildVariableAssignment(
if (current->op() != the_hole->op() && variable->is_this()) {
value = BuildHoleCheckElseThrow(current, variable, value, bailout_id);
}
+ } else if (mode == CONST && op != Token::INIT &&
+ variable->is_sloppy_function_name()) {
+ // Non-initializing assignment to sloppy function names is
+ // - exception in strict mode.
+ // - ignored in sloppy mode.
+ DCHECK(!variable->binding_needs_init());
+ if (variable->throw_on_const_assignment(language_mode())) {
+ return BuildThrowConstAssignError(bailout_id);
+ }
+ return value;
} else if (mode == CONST && op != Token::INIT) {
if (variable->binding_needs_init()) {
Node* current = environment()->Lookup(variable);
@@ -3481,16 +3491,7 @@ Node* AstGraphBuilder::BuildVariableAssignment(
case VariableLocation::CONTEXT: {
// Context variable (potentially up the context chain).
int depth = current_scope()->ContextChainLength(variable->scope());
- if (mode == CONST_LEGACY && op != Token::INIT) {
- // Non-initializing assignment to legacy const is
- // - exception in strict mode.
- // - ignored in sloppy mode.
- if (is_strict(language_mode())) {
- return BuildThrowConstAssignError(bailout_id);
- }
- return value;
- } else if (mode == LET && op != Token::INIT &&
- variable->binding_needs_init()) {
+ if (mode == LET && op != Token::INIT && variable->binding_needs_init()) {
// Perform an initialization check for let declared variables.
const Operator* op =
javascript()->LoadContext(depth, variable->index(), false);
@@ -3506,6 +3507,16 @@ Node* AstGraphBuilder::BuildVariableAssignment(
Node* current = NewNode(op, current_context());
value = BuildHoleCheckElseThrow(current, variable, value, bailout_id);
}
+ } else if (mode == CONST && op != Token::INIT &&
+ variable->is_sloppy_function_name()) {
+ // Non-initializing assignment to sloppy function names is
+ // - exception in strict mode.
+ // - ignored in sloppy mode.
+ DCHECK(!variable->binding_needs_init());
+ if (variable->throw_on_const_assignment(language_mode())) {
+ return BuildThrowConstAssignError(bailout_id);
+ }
+ return value;
} else if (mode == CONST && op != Token::INIT) {
if (variable->binding_needs_init()) {
const Operator* op =
@@ -3688,9 +3699,8 @@ Node* AstGraphBuilder::BuildToObject(Node* input, BailoutId bailout_id) {
return object;
}
-
Node* AstGraphBuilder::BuildSetHomeObject(Node* value, Node* home_object,
- ObjectLiteralProperty* property,
+ LiteralProperty* property,
int slot_number) {
Expression* expr = property->value();
if (!FunctionLiteral::NeedsHomeObject(expr)) return value;
@@ -3989,8 +3999,8 @@ Node* AstGraphBuilder::TryFastToName(Node* input) {
bool AstGraphBuilder::CheckOsrEntry(IterationStatement* stmt) {
if (info()->osr_ast_id() == stmt->OsrEntryId()) {
- info()->set_osr_expr_stack_height(std::max(
- environment()->stack_height(), info()->osr_expr_stack_height()));
+ DCHECK_EQ(-1, info()->osr_expr_stack_height());
+ info()->set_osr_expr_stack_height(environment()->stack_height());
return true;
}
return false;
@@ -4183,9 +4193,39 @@ void AstGraphBuilder::Environment::Merge(Environment* other) {
}
}
+void AstGraphBuilder::Environment::PrepareForOsrEntry() {
+ int size = static_cast<int>(values()->size());
+ Graph* graph = builder_->graph();
+
+ // Set the control and effect to the OSR loop entry.
+ Node* osr_loop_entry = graph->NewNode(builder_->common()->OsrLoopEntry(),
+ graph->start(), graph->start());
+ UpdateControlDependency(osr_loop_entry);
+ UpdateEffectDependency(osr_loop_entry);
+ // Set OSR values.
+ for (int i = 0; i < size; ++i) {
+ values()->at(i) =
+ graph->NewNode(builder_->common()->OsrValue(i), osr_loop_entry);
+ }
+
+ // Set the contexts.
+ // The innermost context is the OSR value, and the outer contexts are
+ // reconstructed by dynamically walking up the context chain.
+ Node* osr_context = nullptr;
+ const Operator* op =
+ builder_->javascript()->LoadContext(0, Context::PREVIOUS_INDEX, true);
+ const Operator* op_inner =
+ builder_->common()->OsrValue(Linkage::kOsrContextSpillSlotIndex);
+ int last = static_cast<int>(contexts()->size() - 1);
+ for (int i = last; i >= 0; i--) {
+ osr_context = (i == last) ? graph->NewNode(op_inner, osr_loop_entry)
+ : graph->NewNode(op, osr_context, osr_context,
+ osr_loop_entry);
+ contexts()->at(i) = osr_context;
+ }
+}
-void AstGraphBuilder::Environment::PrepareForLoop(BitVector* assigned,
- bool is_osr) {
+void AstGraphBuilder::Environment::PrepareForLoop(BitVector* assigned) {
int size = static_cast<int>(values()->size());
Node* control = builder_->NewLoop();
@@ -4220,40 +4260,6 @@ void AstGraphBuilder::Environment::PrepareForLoop(BitVector* assigned,
contexts()->at(i) = builder_->NewPhi(1, context, control);
}
}
-
- if (is_osr) {
- // Merge OSR values as inputs to the phis of the loop.
- Graph* graph = builder_->graph();
- Node* osr_loop_entry = builder_->graph()->NewNode(
- builder_->common()->OsrLoopEntry(), graph->start(), graph->start());
-
- builder_->MergeControl(control, osr_loop_entry);
- builder_->MergeEffect(effect, osr_loop_entry, control);
-
- for (int i = 0; i < size; ++i) {
- Node* value = values()->at(i);
- Node* osr_value =
- graph->NewNode(builder_->common()->OsrValue(i), osr_loop_entry);
- values()->at(i) = builder_->MergeValue(value, osr_value, control);
- }
-
- // Rename all the contexts in the environment.
- // The innermost context is the OSR value, and the outer contexts are
- // reconstructed by dynamically walking up the context chain.
- Node* osr_context = nullptr;
- const Operator* op =
- builder_->javascript()->LoadContext(0, Context::PREVIOUS_INDEX, true);
- const Operator* op_inner =
- builder_->common()->OsrValue(Linkage::kOsrContextSpillSlotIndex);
- int last = static_cast<int>(contexts()->size() - 1);
- for (int i = last; i >= 0; i--) {
- Node* context = contexts()->at(i);
- osr_context = (i == last) ? graph->NewNode(op_inner, osr_loop_entry)
- : graph->NewNode(op, osr_context, osr_context,
- osr_loop_entry);
- contexts()->at(i) = builder_->MergeValue(context, osr_context, control);
- }
- }
}