summaryrefslogtreecommitdiff
path: root/deps/v8/src/interpreter/bytecode-generator.cc
diff options
context:
space:
mode:
authorMichaël Zasso <targos@protonmail.com>2022-09-21 13:28:42 +0200
committerMichaël Zasso <targos@protonmail.com>2022-10-11 07:24:33 +0200
commit6bd756d7c6dfb7dc25daee329ad70df68c14223e (patch)
treeaf93818c545f5bd04cafd4a0c19817e19a475641 /deps/v8/src/interpreter/bytecode-generator.cc
parent624dadb00706a9fc08f919ac72941cdaba7e3ec9 (diff)
downloadnode-new-6bd756d7c6dfb7dc25daee329ad70df68c14223e.tar.gz
deps: update V8 to 10.7.193.13
PR-URL: https://github.com/nodejs/node/pull/44741 Fixes: https://github.com/nodejs/node/issues/44650 Fixes: https://github.com/nodejs/node/issues/37472 Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl> Reviewed-By: Jiawen Geng <technicalcute@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com>
Diffstat (limited to 'deps/v8/src/interpreter/bytecode-generator.cc')
-rw-r--r--deps/v8/src/interpreter/bytecode-generator.cc248
1 files changed, 176 insertions, 72 deletions
diff --git a/deps/v8/src/interpreter/bytecode-generator.cc b/deps/v8/src/interpreter/bytecode-generator.cc
index 4a0299df55..c027fb8b07 100644
--- a/deps/v8/src/interpreter/bytecode-generator.cc
+++ b/deps/v8/src/interpreter/bytecode-generator.cc
@@ -23,16 +23,15 @@
#include "src/interpreter/bytecode-jump-table.h"
#include "src/interpreter/bytecode-label.h"
#include "src/interpreter/bytecode-register-allocator.h"
+#include "src/interpreter/bytecode-register-optimizer.h"
#include "src/interpreter/bytecode-register.h"
#include "src/interpreter/control-flow-builders.h"
#include "src/logging/local-logger.h"
#include "src/logging/log.h"
#include "src/numbers/conversions.h"
#include "src/objects/debug-objects.h"
-#include "src/objects/literal-objects-inl.h"
-#include "src/objects/objects-inl.h"
#include "src/objects/smi.h"
-#include "src/objects/template-objects-inl.h"
+#include "src/objects/template-objects.h"
#include "src/parsing/parse-info.h"
#include "src/parsing/token.h"
#include "src/utils/ostreams.h"
@@ -200,7 +199,7 @@ class V8_NODISCARD BytecodeGenerator::ControlScope::DeferredCommands final {
// There's always a rethrow path.
// TODO(leszeks): We could decouple deferred_ index and token to allow us
// to still push this lazily.
- STATIC_ASSERT(kRethrowToken == 0);
+ static_assert(kRethrowToken == 0);
deferred_.push_back({CMD_RETHROW, nullptr, kRethrowToken});
}
@@ -2016,6 +2015,8 @@ void BytecodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) {
VisitForAccumulatorValue(stmt->tag());
if (use_jump_table) {
+ // Release temps so that they can be reused in clauses.
+ RegisterAllocationScope allocation_scope(this);
// This also fills empty slots in jump table.
Register r2 = register_allocator()->NewRegister();
@@ -2095,6 +2096,7 @@ void BytecodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) {
case_compare_ctr++);
}
}
+ register_allocator()->ReleaseRegister(tag_holder);
}
// For fall-throughs after comparisons (or out-of-range/non-Smi's for jump
@@ -2246,7 +2248,8 @@ void BytecodeGenerator::VisitIterationBody(IterationStatement* stmt,
}
void BytecodeGenerator::VisitDoWhileStatement(DoWhileStatement* stmt) {
- LoopBuilder loop_builder(builder(), block_coverage_builder_, stmt);
+ LoopBuilder loop_builder(builder(), block_coverage_builder_, stmt,
+ feedback_spec());
if (stmt->cond()->ToBooleanIsFalse()) {
// Since we know that the condition is false, we don't create a loop.
// Therefore, we don't create a LoopScope (and thus we don't create a header
@@ -2268,7 +2271,8 @@ void BytecodeGenerator::VisitDoWhileStatement(DoWhileStatement* stmt) {
}
void BytecodeGenerator::VisitWhileStatement(WhileStatement* stmt) {
- LoopBuilder loop_builder(builder(), block_coverage_builder_, stmt);
+ LoopBuilder loop_builder(builder(), block_coverage_builder_, stmt,
+ feedback_spec());
if (stmt->cond()->ToBooleanIsFalse()) {
// If the condition is false there is no need to generate the loop.
@@ -2291,7 +2295,8 @@ void BytecodeGenerator::VisitForStatement(ForStatement* stmt) {
Visit(stmt->init());
}
- LoopBuilder loop_builder(builder(), block_coverage_builder_, stmt);
+ LoopBuilder loop_builder(builder(), block_coverage_builder_, stmt,
+ feedback_spec());
if (stmt->cond() && stmt->cond()->ToBooleanIsFalse()) {
// If the condition is known to be false there is no need to generate
// body, next or condition blocks. Init block should be generated.
@@ -2343,7 +2348,8 @@ void BytecodeGenerator::VisitForInStatement(ForInStatement* stmt) {
// The loop
{
- LoopBuilder loop_builder(builder(), block_coverage_builder_, stmt);
+ LoopBuilder loop_builder(builder(), block_coverage_builder_, stmt,
+ feedback_spec());
LoopScope loop_scope(this, &loop_builder);
builder()->SetExpressionAsStatementPosition(stmt->each());
builder()->ForInContinue(index, cache_length);
@@ -2414,39 +2420,43 @@ void BytecodeGenerator::VisitForOfStatement(ForOfStatement* stmt) {
BuildTryFinally(
// Try block.
[&]() {
- Register next_result = register_allocator()->NewRegister();
-
- LoopBuilder loop_builder(builder(), block_coverage_builder_, stmt);
+ LoopBuilder loop_builder(builder(), block_coverage_builder_, stmt,
+ feedback_spec());
LoopScope loop_scope(this, &loop_builder);
builder()->LoadTrue().StoreAccumulatorInRegister(done);
- // Call the iterator's .next() method. Break from the loop if the `done`
- // property is truthy, otherwise load the value from the iterator result
- // and append the argument.
- builder()->SetExpressionAsStatementPosition(stmt->each());
- BuildIteratorNext(iterator, next_result);
- builder()->LoadNamedProperty(
- next_result, ast_string_constants()->done_string(),
- feedback_index(feedback_spec()->AddLoadICSlot()));
- loop_builder.BreakIfTrue(ToBooleanMode::kConvertToBoolean);
+ {
+ RegisterAllocationScope allocation_scope(this);
+ Register next_result = register_allocator()->NewRegister();
- builder()
- // value = value.value
- ->LoadNamedProperty(
- next_result, ast_string_constants()->value_string(),
- feedback_index(feedback_spec()->AddLoadICSlot()));
- // done = false, before the assignment to each happens, so that done is
- // false if the assignment throws.
- builder()
- ->StoreAccumulatorInRegister(next_result)
- .LoadFalse()
- .StoreAccumulatorInRegister(done);
+ // Call the iterator's .next() method. Break from the loop if the
+ // `done` property is truthy, otherwise load the value from the
+ // iterator result and append the argument.
+ builder()->SetExpressionAsStatementPosition(stmt->each());
+ BuildIteratorNext(iterator, next_result);
+ builder()->LoadNamedProperty(
+ next_result, ast_string_constants()->done_string(),
+ feedback_index(feedback_spec()->AddLoadICSlot()));
+ loop_builder.BreakIfTrue(ToBooleanMode::kConvertToBoolean);
- // Assign to the 'each' target.
- AssignmentLhsData lhs_data = PrepareAssignmentLhs(stmt->each());
- builder()->LoadAccumulatorWithRegister(next_result);
- BuildAssignment(lhs_data, Token::ASSIGN, LookupHoistingMode::kNormal);
+ builder()
+ // value = value.value
+ ->LoadNamedProperty(
+ next_result, ast_string_constants()->value_string(),
+ feedback_index(feedback_spec()->AddLoadICSlot()));
+ // done = false, before the assignment to each happens, so that done
+ // is false if the assignment throws.
+ builder()
+ ->StoreAccumulatorInRegister(next_result)
+ .LoadFalse()
+ .StoreAccumulatorInRegister(done);
+
+ // Assign to the 'each' target.
+ AssignmentLhsData lhs_data = PrepareAssignmentLhs(stmt->each());
+ builder()->LoadAccumulatorWithRegister(next_result);
+ BuildAssignment(lhs_data, Token::ASSIGN, LookupHoistingMode::kNormal);
+ }
VisitIterationBody(stmt, &loop_builder);
},
@@ -2515,7 +2525,7 @@ void BytecodeGenerator::VisitFunctionLiteral(FunctionLiteral* expr) {
DCHECK_EQ(expr->scope()->outer_scope(), current_scope());
uint8_t flags = CreateClosureFlags::Encode(
expr->pretenure(), closure_scope()->is_function_scope(),
- info()->flags().might_always_opt());
+ info()->flags().might_always_turbofan());
size_t entry = builder()->AllocateDeferredConstantPoolEntry();
builder()->CreateClosure(entry, GetCachedCreateClosureSlot(expr), flags);
function_literals_.push_back(std::make_pair(expr, entry));
@@ -2578,6 +2588,8 @@ void BytecodeGenerator::BuildClassLiteral(ClassLiteral* expr, Register name) {
->LoadLiteral(class_name)
.StoreAccumulatorInRegister(brand)
.CallRuntime(Runtime::kCreatePrivateBrandSymbol, brand);
+ register_allocator()->ReleaseRegister(brand);
+
BuildVariableAssignment(expr->scope()->brand(), Token::INIT,
HoleCheckMode::kElided);
}
@@ -2700,8 +2712,6 @@ void BytecodeGenerator::BuildClassLiteral(ClassLiteral* expr, Register name) {
builder()->CallRuntime(Runtime::kDefineClass, args);
}
- Register prototype = register_allocator()->NewRegister();
- builder()->StoreAccumulatorInRegister(prototype);
// Assign to the home object variable. Accumulator already contains the
// prototype.
@@ -2802,11 +2812,19 @@ void BytecodeGenerator::VisitClassLiteral(ClassLiteral* expr, Register name) {
// Make sure to associate the source position for the class
// after the block context is created. Otherwise we have a mismatch
// between the scope and the context, where we already are in a
- // block context for the class, but not yet in the class scope.
- BytecodeSourceInfo source_info = builder()->PopSourcePosition();
+ // block context for the class, but not yet in the class scope. Only do
+ // this if the current source position is inside the class scope though.
+ // For example:
+ // * `var x = class {};` will break on `class` which is inside
+ // the class scope, so we expect the BlockContext to be pushed.
+ //
+ // * `new class x {};` will break on `new` which is outside the
+ // class scope, so we expect the BlockContext to not be pushed yet.
+ base::Optional<BytecodeSourceInfo> source_info =
+ builder()->MaybePopSourcePosition(expr->scope()->start_position());
BuildNewLocalBlockContext(expr->scope());
ContextScope scope(this, expr->scope());
- builder()->PushSourcePosition(source_info);
+ if (source_info) builder()->PushSourcePosition(*source_info);
BuildClassLiteral(expr, name);
} else {
BuildClassLiteral(expr, name);
@@ -3322,7 +3340,7 @@ void BytecodeGenerator::BuildFillArrayWithIterator(
DCHECK(index.is_valid());
DCHECK(value.is_valid());
- LoopBuilder loop_builder(builder(), nullptr, nullptr);
+ LoopBuilder loop_builder(builder(), nullptr, nullptr, feedback_spec());
LoopScope loop_scope(this, &loop_builder);
// Call the iterator's .next() method. Break from the loop if the `done`
@@ -3351,8 +3369,10 @@ void BytecodeGenerator::BuildFillArrayWithIterator(
void BytecodeGenerator::BuildCreateArrayLiteral(
const ZonePtrList<Expression>* elements, ArrayLiteral* expr) {
RegisterAllocationScope register_scope(this);
- Register index = register_allocator()->NewRegister();
+ // Make this the first register allocated so that it has a chance of aliasing
+ // the next register allocated after returning from this function.
Register array = register_allocator()->NewRegister();
+ Register index = register_allocator()->NewRegister();
SharedFeedbackSlot element_slot(feedback_spec(),
FeedbackSlotKind::kStoreInArrayLiteral);
ZonePtrList<Expression>::const_iterator current = elements->begin();
@@ -3517,6 +3537,21 @@ void BytecodeGenerator::VisitVariableProxy(VariableProxy* proxy) {
BuildVariableLoad(proxy->var(), proxy->hole_check_mode());
}
+bool BytecodeGenerator::IsVariableInRegister(Variable* var, Register reg) {
+ BytecodeRegisterOptimizer* optimizer = builder()->GetRegisterOptimizer();
+ if (optimizer) {
+ return optimizer->IsVariableInRegister(var, reg);
+ }
+ return false;
+}
+
+void BytecodeGenerator::SetVariableInRegister(Variable* var, Register reg) {
+ BytecodeRegisterOptimizer* optimizer = builder()->GetRegisterOptimizer();
+ if (optimizer) {
+ optimizer->SetVariableInRegister(var, reg);
+ }
+}
+
void BytecodeGenerator::BuildVariableLoad(Variable* variable,
HoleCheckMode hole_check_mode,
TypeofMode typeof_mode) {
@@ -3576,12 +3611,20 @@ void BytecodeGenerator::BuildVariableLoad(Variable* variable,
(variable->maybe_assigned() == kNotAssigned)
? BytecodeArrayBuilder::kImmutableSlot
: BytecodeArrayBuilder::kMutableSlot;
+ Register acc = Register::virtual_accumulator();
+ if (immutable == BytecodeArrayBuilder::kImmutableSlot &&
+ IsVariableInRegister(variable, acc)) {
+ return;
+ }
builder()->LoadContextSlot(context_reg, variable->index(), depth,
immutable);
if (hole_check_mode == HoleCheckMode::kRequired) {
BuildThrowIfHole(variable);
}
+ if (immutable == BytecodeArrayBuilder::kImmutableSlot) {
+ SetVariableInRegister(variable, acc);
+ }
break;
}
case VariableLocation::LOOKUP: {
@@ -4719,7 +4762,7 @@ void BytecodeGenerator::VisitYield(Yield* expr) {
Runtime::kInlineGeneratorGetResumeMode, generator_object());
// Now dispatch on resume mode.
- STATIC_ASSERT(JSGeneratorObject::kNext + 1 == JSGeneratorObject::kReturn);
+ static_assert(JSGeneratorObject::kNext + 1 == JSGeneratorObject::kReturn);
BytecodeJumpTable* jump_table =
builder()->AllocateJumpTable(2, JSGeneratorObject::kNext);
@@ -4853,7 +4896,7 @@ void BytecodeGenerator::VisitYieldStar(YieldStar* expr) {
// - One for awaiting the iterator result yielded by the delegated
// iterator
- LoopBuilder loop_builder(builder(), nullptr, nullptr);
+ LoopBuilder loop_builder(builder(), nullptr, nullptr, feedback_spec());
LoopScope loop_scope(this, &loop_builder);
{
@@ -4868,7 +4911,7 @@ void BytecodeGenerator::VisitYieldStar(YieldStar* expr) {
// Fallthrough to default case.
// TODO(ignition): Add debug code to check that {resume_mode} really is
// {JSGeneratorObject::kNext} in this case.
- STATIC_ASSERT(JSGeneratorObject::kNext == 0);
+ static_assert(JSGeneratorObject::kNext == 0);
{
FeedbackSlot slot = feedback_spec()->AddCallICSlot();
builder()->CallProperty(iterator.next(), iterator_and_input,
@@ -4876,7 +4919,7 @@ void BytecodeGenerator::VisitYieldStar(YieldStar* expr) {
builder()->Jump(after_switch.New());
}
- STATIC_ASSERT(JSGeneratorObject::kReturn == 1);
+ static_assert(JSGeneratorObject::kReturn == 1);
builder()->Bind(switch_jump_table, JSGeneratorObject::kReturn);
{
const AstRawString* return_string =
@@ -4897,7 +4940,7 @@ void BytecodeGenerator::VisitYieldStar(YieldStar* expr) {
}
}
- STATIC_ASSERT(JSGeneratorObject::kThrow == 2);
+ static_assert(JSGeneratorObject::kThrow == 2);
builder()->Bind(switch_jump_table, JSGeneratorObject::kThrow);
{
const AstRawString* throw_string =
@@ -5605,34 +5648,70 @@ void BytecodeGenerator::VisitCallSuper(Call* expr) {
// Prepare the constructor to the super call.
Register this_function = VisitForRegisterValue(super->this_function_var());
- Register constructor = register_allocator()->NewRegister();
- builder()
- ->LoadAccumulatorWithRegister(this_function)
- .GetSuperConstructor(constructor);
+ // This register will initially hold the constructor, then afterward it will
+ // hold the instance -- the lifetimes of the two don't need to overlap, and
+ // this way FindNonDefaultConstructor can choose to write either the instance
+ // or the constructor into the same register.
+ Register constructor_then_instance = register_allocator()->NewRegister();
+
+ BytecodeLabel super_ctor_call_done;
+ bool omit_super_ctor = FLAG_omit_default_ctors &&
+ IsDerivedConstructor(info()->literal()->kind());
if (spread_position == Call::kHasNonFinalSpread) {
- // First generate the array containing all arguments.
+ RegisterAllocationScope register_scope(this);
+ RegisterList construct_args(constructor_then_instance);
+ const Register& constructor = constructor_then_instance;
+
+ // Generate the array containing all arguments.
BuildCreateArrayLiteral(args, nullptr);
+ Register args_array =
+ register_allocator()->GrowRegisterList(&construct_args);
+ builder()->StoreAccumulatorInRegister(args_array);
+
+ Register new_target =
+ register_allocator()->GrowRegisterList(&construct_args);
+ VisitForRegisterValue(super->new_target_var(), new_target);
+
+ if (omit_super_ctor) {
+ BuildSuperCallOptimization(this_function, new_target,
+ constructor_then_instance,
+ &super_ctor_call_done);
+ } else {
+ builder()
+ ->LoadAccumulatorWithRegister(this_function)
+ .GetSuperConstructor(constructor);
+ }
// Check if the constructor is in fact a constructor.
builder()->ThrowIfNotSuperConstructor(constructor);
// Now pass that array to %reflect_construct.
- RegisterList construct_args = register_allocator()->NewRegisterList(3);
- builder()->StoreAccumulatorInRegister(construct_args[1]);
- builder()->MoveRegister(constructor, construct_args[0]);
- VisitForRegisterValue(super->new_target_var(), construct_args[2]);
builder()->CallJSRuntime(Context::REFLECT_CONSTRUCT_INDEX, construct_args);
} else {
+ RegisterAllocationScope register_scope(this);
RegisterList args_regs = register_allocator()->NewGrowableRegisterList();
VisitArguments(args, &args_regs);
+ // The new target is loaded into the new_target register from the
+ // {new.target} variable.
+ Register new_target = register_allocator()->NewRegister();
+ VisitForRegisterValue(super->new_target_var(), new_target);
+
+ const Register& constructor = constructor_then_instance;
+ if (omit_super_ctor) {
+ BuildSuperCallOptimization(this_function, new_target,
+ constructor_then_instance,
+ &super_ctor_call_done);
+ } else {
+ builder()
+ ->LoadAccumulatorWithRegister(this_function)
+ .GetSuperConstructor(constructor);
+ }
+
// Check if the constructor is in fact a constructor.
builder()->ThrowIfNotSuperConstructor(constructor);
-
- // The new target is loaded into the accumulator from the
- // {new.target} variable.
- VisitForAccumulatorValue(super->new_target_var());
+ builder()->LoadAccumulatorWithRegister(new_target);
builder()->SetExpressionPosition(expr);
int feedback_slot_index = feedback_index(feedback_spec()->AddCallICSlot());
@@ -5653,6 +5732,11 @@ void BytecodeGenerator::VisitCallSuper(Call* expr) {
}
}
+ // From here onwards, constructor_then_instance will hold the instance.
+ const Register& instance = constructor_then_instance;
+ builder()->StoreAccumulatorInRegister(instance);
+ builder()->Bind(&super_ctor_call_done);
+
// Explicit calls to the super constructor using super() perform an
// implicit binding assignment to the 'this' variable.
//
@@ -5660,12 +5744,10 @@ void BytecodeGenerator::VisitCallSuper(Call* expr) {
// 'this' isn't accessed in default constructors.
if (!IsDefaultConstructor(info()->literal()->kind())) {
Variable* var = closure_scope()->GetReceiverScope()->receiver();
+ builder()->LoadAccumulatorWithRegister(instance);
BuildVariableAssignment(var, Token::INIT, HoleCheckMode::kRequired);
}
- Register instance = register_allocator()->NewRegister();
- builder()->StoreAccumulatorInRegister(instance);
-
// The constructor scope always needs ScopeInfo, so we are certain that
// the first constructor scope found in the outer scope chain is the
// scope that we are looking for for this super() call.
@@ -5705,6 +5787,17 @@ void BytecodeGenerator::VisitCallSuper(Call* expr) {
builder()->LoadAccumulatorWithRegister(instance);
}
+void BytecodeGenerator::BuildSuperCallOptimization(
+ Register this_function, Register new_target,
+ Register constructor_then_instance, BytecodeLabel* super_ctor_call_done) {
+ DCHECK(FLAG_omit_default_ctors);
+ RegisterList output = register_allocator()->NewRegisterList(2);
+ builder()->FindNonDefaultConstructor(this_function, new_target, output);
+ builder()->MoveRegister(output[1], constructor_then_instance);
+ builder()->LoadAccumulatorWithRegister(output[0]).JumpIfTrue(
+ ToBooleanMode::kAlreadyBoolean, super_ctor_call_done);
+}
+
void BytecodeGenerator::VisitCallNew(CallNew* expr) {
RegisterList args = register_allocator()->NewGrowableRegisterList();
@@ -6157,6 +6250,14 @@ void BytecodeGenerator::BuildLiteralCompareNil(
}
}
+void BytecodeGenerator::BuildLiteralStrictCompareBoolean(Literal* literal) {
+ DCHECK(literal->IsBooleanLiteral());
+ Register result = register_allocator()->NewRegister();
+ builder()->StoreAccumulatorInRegister(result);
+ builder()->LoadBoolean(literal->AsBooleanLiteral());
+ builder()->CompareReference(result);
+}
+
void BytecodeGenerator::VisitCompareOperation(CompareOperation* expr) {
Expression* sub_expr;
Literal* literal;
@@ -6172,6 +6273,11 @@ void BytecodeGenerator::VisitCompareOperation(CompareOperation* expr) {
} else {
builder()->CompareTypeOf(literal_flag);
}
+ } else if (expr->IsLiteralStrictCompareBoolean(&sub_expr, &literal)) {
+ DCHECK(expr->op() == Token::EQ_STRICT);
+ VisitForAccumulatorValue(sub_expr);
+ builder()->SetExpressionPosition(expr);
+ BuildLiteralStrictCompareBoolean(literal);
} else if (expr->IsLiteralCompareUndefined(&sub_expr)) {
VisitForAccumulatorValue(sub_expr);
builder()->SetExpressionPosition(expr);
@@ -6182,7 +6288,6 @@ void BytecodeGenerator::VisitCompareOperation(CompareOperation* expr) {
BuildLiteralCompareNil(expr->op(), BytecodeArrayBuilder::kNullValue);
} else {
if (expr->op() == Token::IN && expr->left()->IsPrivateName()) {
- DCHECK(FLAG_harmony_private_brand_checks);
Variable* var = expr->left()->AsVariableProxy()->var();
if (IsPrivateMethodOrAccessorVariableMode(var->mode())) {
BuildPrivateMethodIn(var, expr->right());
@@ -6337,16 +6442,11 @@ void BytecodeGenerator::BuildGetIterator(IteratorType hint) {
feedback_index(feedback_spec()->AddCallICSlot());
// Let method be GetMethod(obj, @@iterator) and
- // iterator be Call(method, obj).
+ // iterator be Call(method, obj). If iterator is
+ // not JSReceiver, then throw TypeError.
builder()->StoreAccumulatorInRegister(obj).GetIterator(
obj, load_feedback_index, call_feedback_index);
}
-
- // If Type(iterator) is not Object, throw a TypeError exception.
- BytecodeLabel no_type_error;
- builder()->JumpIfJSReceiver(&no_type_error);
- builder()->CallRuntime(Runtime::kThrowSymbolIteratorInvalid);
- builder()->Bind(&no_type_error);
}
}
@@ -6852,6 +6952,7 @@ void BytecodeGenerator::BuildNewLocalActivationContext() {
Register arg = register_allocator()->NewRegister();
builder()->LoadLiteral(scope).StoreAccumulatorInRegister(arg).CallRuntime(
Runtime::kNewFunctionContext, arg);
+ register_allocator()->ReleaseRegister(arg);
}
}
@@ -6895,6 +6996,8 @@ void BytecodeGenerator::BuildNewLocalWithContext(Scope* scope) {
builder()->ToObject(extension_object);
builder()->CreateWithContext(extension_object, scope);
+
+ register_allocator()->ReleaseRegister(extension_object);
}
void BytecodeGenerator::BuildNewLocalCatchContext(Scope* scope) {
@@ -6904,6 +7007,7 @@ void BytecodeGenerator::BuildNewLocalCatchContext(Scope* scope) {
Register exception = register_allocator()->NewRegister();
builder()->StoreAccumulatorInRegister(exception);
builder()->CreateCatchContext(exception, scope);
+ register_allocator()->ReleaseRegister(exception);
}
void BytecodeGenerator::VisitLiteralAccessor(LiteralProperty* property,