[Interpreter] Fix a register allocation bug and add a DCHECK.

BUG=v8:4280
LOG=N

Review URL: https://codereview.chromium.org/1413703007

Cr-Commit-Position: refs/heads/master@{#31604}
This commit is contained in:
rmcilroy 2015-10-27 06:33:11 -07:00 committed by Commit bot
parent f1aa556278
commit f85c410626
4 changed files with 48 additions and 3 deletions

View File

@ -1061,6 +1061,15 @@ Register TemporaryRegisterScope::NewRegister() {
}
bool TemporaryRegisterScope::RegisterIsAllocatedInThisScope(
Register reg) const {
for (auto i = allocated_.begin(); i != allocated_.end(); i++) {
if (*i == reg.index()) return true;
}
return false;
}
void TemporaryRegisterScope::PrepareForConsecutiveAllocations(size_t count) {
if (static_cast<int>(count) > next_consecutive_count_) {
next_consecutive_register_ =

View File

@ -316,6 +316,8 @@ class TemporaryRegisterScope {
void PrepareForConsecutiveAllocations(size_t count);
Register NextConsecutiveRegister();
bool RegisterIsAllocatedInThisScope(Register reg) const;
private:
void* operator new(size_t size);
void operator delete(void* p);

View File

@ -193,6 +193,8 @@ class BytecodeGenerator::ExpressionResultScope {
bool result_identified() const { return result_identified_; }
const TemporaryRegisterScope* allocator() const { return &allocator_; }
private:
BytecodeGenerator* generator_;
Expression::Context kind_;
@ -252,7 +254,8 @@ class BytecodeGenerator::RegisterResultScope final
virtual void SetResultInRegister(Register reg) {
DCHECK(builder()->RegisterIsParameterOrLocal(reg) ||
builder()->RegisterIsTemporary(reg));
(builder()->RegisterIsTemporary(reg) &&
!allocator()->RegisterIsAllocatedInThisScope(reg)));
result_register_ = reg;
set_result_identified();
}
@ -475,6 +478,8 @@ void BytecodeGenerator::VisitDeclarations(
void BytecodeGenerator::VisitExpressionStatement(ExpressionStatement* stmt) {
// TODO(rmcilroy): Replace this with a StatementResultScope when it exists.
EffectResultScope effect_scope(this);
VisitForEffect(stmt->expression());
}
@ -522,6 +527,7 @@ void BytecodeGenerator::VisitBreakStatement(BreakStatement* stmt) {
void BytecodeGenerator::VisitReturnStatement(ReturnStatement* stmt) {
EffectResultScope effect_scope(this);
VisitForAccumulatorValue(stmt->expression());
builder()->Return();
}
@ -1484,7 +1490,7 @@ void BytecodeGenerator::VisitCountOperation(CountOperation* expr) {
// Save result for postfix expressions.
if (is_postfix) {
old_value = execution_result()->NewRegister();
old_value = execution_result()->outer()->NewRegister();
builder()->StoreAccumulatorInRegister(old_value);
}

View File

@ -2988,15 +2988,21 @@ TEST(CountOperators) {
FeedbackVectorSpec feedback_spec(&zone);
FeedbackVectorSlot slot1 = feedback_spec.AddLoadICSlot();
FeedbackVectorSlot slot2 = feedback_spec.AddStoreICSlot();
Handle<i::TypeFeedbackVector> vector =
i::NewTypeFeedbackVector(helper.isolate(), &feedback_spec);
FeedbackVectorSpec store_feedback_spec(&zone);
FeedbackVectorSlot store_slot = store_feedback_spec.AddStoreICSlot();
Handle<i::TypeFeedbackVector> store_vector =
i::NewTypeFeedbackVector(helper.isolate(), &store_feedback_spec);
int closure = Register::function_closure().index();
int first_context_slot = Context::MIN_CONTEXT_SLOTS;
int object_literal_flags =
ObjectLiteral::kFastElements | ObjectLiteral::kDisableMementos;
int array_literal_flags =
ArrayLiteral::kDisableMementos | ArrayLiteral::kShallowElements;
ExpectedSnippet<InstanceType> snippets[] = {
{"var a = 1; return ++a;",
@ -3179,6 +3185,28 @@ TEST(CountOperators) {
},
1,
{InstanceType::SHARED_FUNCTION_INFO_TYPE}},
{"var idx = 1; var a = [1, 2]; return a[idx++] = 2;",
3 * kPointerSize,
1,
26,
{
B(LdaSmi8), U8(1), //
B(Star), R(0), //
B(LdaConstant), U8(0), //
B(CreateArrayLiteral), U8(0), U8(array_literal_flags), //
B(Star), R(1), //
B(Ldar), R(0), //
B(ToNumber), //
B(Star), R(2), //
B(Inc), //
B(Star), R(0), //
B(LdaSmi8), U8(2), //
B(KeyedStoreICSloppy), R(1), R(2), //
U8(store_vector->GetIndex(store_slot)), //
B(Return), //
},
1,
{InstanceType::FIXED_ARRAY_TYPE}},
};
for (size_t i = 0; i < arraysize(snippets); i++) {