From 325d3ef224c8a6626e96011b53d88522b585a633 Mon Sep 17 00:00:00 2001 From: "kasperl@chromium.org" Date: Tue, 2 Feb 2010 07:58:09 +0000 Subject: [PATCH] Remember to update the write barrier when storing into the context in the full compiler. Clobber all input registers in the RecordWrite code when the debug-code flag is set. Review URL: http://codereview.chromium.org/569008 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@3761 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- src/arm/full-codegen-arm.cc | 12 +++++++++--- src/arm/macro-assembler-arm.cc | 8 ++++++++ src/full-codegen.cc | 12 ------------ src/ia32/full-codegen-ia32.cc | 12 +++++++++--- src/ia32/macro-assembler-ia32.cc | 8 ++++++++ src/x64/full-codegen-x64.cc | 12 +++++++++--- src/x64/macro-assembler-x64.cc | 27 +++++++++++++++++++++++++++ 7 files changed, 70 insertions(+), 21 deletions(-) diff --git a/src/arm/full-codegen-arm.cc b/src/arm/full-codegen-arm.cc index 386d201ac0..9f240dd82c 100644 --- a/src/arm/full-codegen-arm.cc +++ b/src/arm/full-codegen-arm.cc @@ -95,8 +95,14 @@ void FullCodeGenerator::Generate(FunctionLiteral* fun, Mode mode) { (num_parameters - 1 - i) * kPointerSize; // Load parameter from stack. __ ldr(r0, MemOperand(fp, parameter_offset)); - // Store it in the context - __ str(r0, MemOperand(cp, Context::SlotOffset(slot->index()))); + // Store it in the context. + __ mov(r1, Operand(Context::SlotOffset(slot->index()))); + __ str(r0, MemOperand(cp, r1)); + // Update the write barrier. This clobbers all involved + // registers, so we have use a third register to avoid + // clobbering cp. + __ mov(r2, Operand(cp)); + __ RecordWrite(r2, r1, r0); } } } @@ -113,7 +119,7 @@ void FullCodeGenerator::Generate(FunctionLiteral* fun, Mode mode) { } // Receiver is just before the parameters on the caller's stack. __ add(r2, fp, Operand(StandardFrameConstants::kCallerSPOffset + - fun->num_parameters() * kPointerSize)); + fun->num_parameters() * kPointerSize)); __ mov(r1, Operand(Smi::FromInt(fun->num_parameters()))); __ stm(db_w, sp, r3.bit() | r2.bit() | r1.bit()); diff --git a/src/arm/macro-assembler-arm.cc b/src/arm/macro-assembler-arm.cc index 6cbd6a57f3..b39404e7f9 100644 --- a/src/arm/macro-assembler-arm.cc +++ b/src/arm/macro-assembler-arm.cc @@ -277,6 +277,14 @@ void MacroAssembler::RecordWrite(Register object, Register offset, str(scratch, MemOperand(object)); bind(&done); + + // Clobber all input registers when running with the debug-code flag + // turned on to provoke errors. + if (FLAG_debug_code) { + mov(object, Operand(bit_cast(kZapValue))); + mov(offset, Operand(bit_cast(kZapValue))); + mov(scratch, Operand(bit_cast(kZapValue))); + } } diff --git a/src/full-codegen.cc b/src/full-codegen.cc index 4a1a7d37c0..29a445256c 100644 --- a/src/full-codegen.cc +++ b/src/full-codegen.cc @@ -54,18 +54,6 @@ namespace internal { void FullCodeGenSyntaxChecker::Check(FunctionLiteral* fun) { Scope* scope = fun->scope(); - - if (scope->num_heap_slots() > 0) { - // We support functions with a local context if they do not have - // parameters that need to be copied into the context. - for (int i = 0, len = scope->num_parameters(); i < len; i++) { - Slot* slot = scope->parameter(i)->slot(); - if (slot != NULL && slot->type() == Slot::CONTEXT) { - BAILOUT("Function has context-allocated parameters."); - } - } - } - VisitDeclarations(scope->declarations()); CHECK_BAILOUT; diff --git a/src/ia32/full-codegen-ia32.cc b/src/ia32/full-codegen-ia32.cc index ba03eafe93..9f9ac56cc1 100644 --- a/src/ia32/full-codegen-ia32.cc +++ b/src/ia32/full-codegen-ia32.cc @@ -95,8 +95,14 @@ void FullCodeGenerator::Generate(FunctionLiteral* fun, Mode mode) { (num_parameters - 1 - i) * kPointerSize; // Load parameter from stack. __ mov(eax, Operand(ebp, parameter_offset)); - // Store it in the context - __ mov(Operand(esi, Context::SlotOffset(slot->index())), eax); + // Store it in the context. + int context_offset = Context::SlotOffset(slot->index()); + __ mov(Operand(esi, context_offset), eax); + // Update the write barrier. This clobbers all involved + // registers, so we have use a third register to avoid + // clobbering esi. + __ mov(ecx, esi); + __ RecordWrite(ecx, context_offset, eax, ebx); } } } @@ -112,7 +118,7 @@ void FullCodeGenerator::Generate(FunctionLiteral* fun, Mode mode) { } // Receiver is just before the parameters on the caller's stack. __ lea(edx, Operand(ebp, StandardFrameConstants::kCallerSPOffset + - fun->num_parameters() * kPointerSize)); + fun->num_parameters() * kPointerSize)); __ push(edx); __ push(Immediate(Smi::FromInt(fun->num_parameters()))); // Arguments to ArgumentsAccessStub: diff --git a/src/ia32/macro-assembler-ia32.cc b/src/ia32/macro-assembler-ia32.cc index 07622bba18..19a380b029 100644 --- a/src/ia32/macro-assembler-ia32.cc +++ b/src/ia32/macro-assembler-ia32.cc @@ -215,6 +215,14 @@ void MacroAssembler::RecordWrite(Register object, int offset, } bind(&done); + + // Clobber all input registers when running with the debug-code flag + // turned on to provoke errors. + if (FLAG_debug_code) { + mov(object, Immediate(bit_cast(kZapValue))); + mov(value, Immediate(bit_cast(kZapValue))); + mov(scratch, Immediate(bit_cast(kZapValue))); + } } diff --git a/src/x64/full-codegen-x64.cc b/src/x64/full-codegen-x64.cc index 60069bdde0..688bfba7c8 100644 --- a/src/x64/full-codegen-x64.cc +++ b/src/x64/full-codegen-x64.cc @@ -95,8 +95,14 @@ void FullCodeGenerator::Generate(FunctionLiteral* fun, Mode mode) { (num_parameters - 1 - i) * kPointerSize; // Load parameter from stack. __ movq(rax, Operand(rbp, parameter_offset)); - // Store it in the context - __ movq(Operand(rsi, Context::SlotOffset(slot->index())), rax); + // Store it in the context. + int context_offset = Context::SlotOffset(slot->index()); + __ movq(Operand(rsi, context_offset), rax); + // Update the write barrier. This clobbers all involved + // registers, so we have use a third register to avoid + // clobbering rsi. + __ movq(rcx, rsi); + __ RecordWrite(rcx, context_offset, rax, rbx); } } } @@ -114,7 +120,7 @@ void FullCodeGenerator::Generate(FunctionLiteral* fun, Mode mode) { } // The receiver is just before the parameters on the caller's stack. __ lea(rdx, Operand(rbp, StandardFrameConstants::kCallerSPOffset + - fun->num_parameters() * kPointerSize)); + fun->num_parameters() * kPointerSize)); __ push(rdx); __ Push(Smi::FromInt(fun->num_parameters())); // Arguments to ArgumentsAccessStub: diff --git a/src/x64/macro-assembler-x64.cc b/src/x64/macro-assembler-x64.cc index 0bb8118532..96b45e8427 100644 --- a/src/x64/macro-assembler-x64.cc +++ b/src/x64/macro-assembler-x64.cc @@ -191,6 +191,17 @@ void MacroAssembler::RecordWrite(Register object, RecordWriteNonSmi(object, offset, value, smi_index); bind(&done); + + // Clobber all input registers when running with the debug-code flag + // turned on to provoke errors. This clobbering repeats the + // clobbering done inside RecordWriteNonSmi but it's necessary to + // avoid having the fast case for smis leave the registers + // unchanged. + if (FLAG_debug_code) { + movq(object, bit_cast(kZapValue), RelocInfo::NONE); + movq(value, bit_cast(kZapValue), RelocInfo::NONE); + movq(smi_index, bit_cast(kZapValue), RelocInfo::NONE); + } } @@ -199,6 +210,14 @@ void MacroAssembler::RecordWriteNonSmi(Register object, Register scratch, Register smi_index) { Label done; + + if (FLAG_debug_code) { + Label okay; + JumpIfNotSmi(object, &okay); + Abort("MacroAssembler::RecordWriteNonSmi cannot deal with smis"); + bind(&okay); + } + // Test that the object address is not in the new space. We cannot // set remembered set bits in the new space. movq(scratch, object); @@ -248,6 +267,14 @@ void MacroAssembler::RecordWriteNonSmi(Register object, } bind(&done); + + // Clobber all input registers when running with the debug-code flag + // turned on to provoke errors. + if (FLAG_debug_code) { + movq(object, bit_cast(kZapValue), RelocInfo::NONE); + movq(scratch, bit_cast(kZapValue), RelocInfo::NONE); + movq(smi_index, bit_cast(kZapValue), RelocInfo::NONE); + } }