Skip to content

Commit 77a71c9

Browse files
author
sgjesse@chromium.org
committed
Fix issue 491: constantpool dump violates ARM debugger assertion for return point
The generation of the return sequence is now protected from having the constant pool emitted inside of it in both compilers. BUG=http://code.google.com/p/v8/issues/detail?id=491 TEST=test/mjsunit/regress/regress-491.js Review URL: http://codereview.chromium.org/362003 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@3215 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
1 parent 3db5a2e commit 77a71c9

8 files changed

Lines changed: 86 additions & 26 deletions

File tree

src/arm/assembler-arm.cc

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1318,6 +1318,11 @@ bool Assembler::ImmediateFitsAddrMode1Instruction(int32_t imm32) {
13181318
}
13191319

13201320

1321+
void Assembler::BlockConstPoolFor(int instructions) {
1322+
BlockConstPoolBefore(pc_offset() + instructions * kInstrSize);
1323+
}
1324+
1325+
13211326
// Debugging
13221327
void Assembler::RecordJSReturn() {
13231328
WriteRecordedPositions();

src/arm/assembler-arm.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -685,6 +685,10 @@ class Assembler : public Malloced {
685685
// Check whether an immediate fits an addressing mode 1 instruction.
686686
bool ImmediateFitsAddrMode1Instruction(int32_t imm32);
687687

688+
// Postpone the generation of the constant pool for the specified number of
689+
// instructions.
690+
void BlockConstPoolFor(int instructions);
691+
688692
// Debugging
689693

690694
// Mark address of the ExitJSFrame code.

src/arm/codegen-arm.cc

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -322,13 +322,22 @@ void CodeGenerator::GenCode(FunctionLiteral* fun) {
322322
Label check_exit_codesize;
323323
masm_->bind(&check_exit_codesize);
324324

325+
// Calculate the exact length of the return sequence and make sure that
326+
// the constant pool is not emitted inside of the return sequence.
327+
int32_t sp_delta = (scope_->num_parameters() + 1) * kPointerSize;
328+
int return_sequence_length = Debug::kARMJSReturnSequenceLength;
329+
if (!masm_->ImmediateFitsAddrMode1Instruction(sp_delta)) {
330+
// Additional mov instruction generated.
331+
return_sequence_length++;
332+
}
333+
masm_->BlockConstPoolFor(return_sequence_length);
334+
325335
// Tear down the frame which will restore the caller's frame pointer and
326336
// the link register.
327337
frame_->Exit();
328338

329339
// Here we use masm_-> instead of the __ macro to avoid the code coverage
330340
// tool from instrumenting as we rely on the code size here.
331-
int32_t sp_delta = (scope_->num_parameters() + 1) * kPointerSize;
332341
masm_->add(sp, sp, Operand(sp_delta));
333342
masm_->Jump(lr);
334343

@@ -338,15 +347,8 @@ void CodeGenerator::GenCode(FunctionLiteral* fun) {
338347
// can be encoded in the instruction and which immediate values requires
339348
// use of an additional instruction for moving the immediate to a temporary
340349
// register.
341-
#ifdef DEBUG
342-
int expected_return_sequence_length = kJSReturnSequenceLength;
343-
if (!masm_->ImmediateFitsAddrMode1Instruction(sp_delta)) {
344-
// Additional mov instruction generated.
345-
expected_return_sequence_length++;
346-
}
347-
ASSERT_EQ(expected_return_sequence_length,
350+
ASSERT_EQ(return_sequence_length,
348351
masm_->InstructionsGeneratedSince(&check_exit_codesize));
349-
#endif
350352
}
351353

352354
// Code generation state must be reset.

src/arm/codegen-arm.h

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -187,10 +187,6 @@ class CodeGenerator: public AstVisitor {
187187

188188
static const int kUnknownIntValue = -1;
189189

190-
// Number of instructions used for the JS return sequence. The constant is
191-
// used by the debugger to patch the JS return sequence.
192-
static const int kJSReturnSequenceLength = 4;
193-
194190
private:
195191
// Construction/Destruction
196192
CodeGenerator(int buffer_size, Handle<Script> script, bool is_eval);

src/arm/debug-arm.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ void BreakLocationIterator::SetDebugBreakAtReturn() {
6161
// Restore the JS frame exit code.
6262
void BreakLocationIterator::ClearDebugBreakAtReturn() {
6363
rinfo()->PatchCode(original_rinfo()->pc(),
64-
CodeGenerator::kJSReturnSequenceLength);
64+
Debug::kARMJSReturnSequenceLength);
6565
}
6666

6767

src/arm/fast-codegen-arm.cc

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
#include "v8.h"
2929

3030
#include "codegen-inl.h"
31+
#include "debug.h"
3132
#include "fast-codegen.h"
3233
#include "parser.h"
3334

@@ -118,34 +119,37 @@ void FastCodeGenerator::EmitReturnSequence(int position) {
118119
__ push(r0);
119120
__ CallRuntime(Runtime::kTraceExit, 1);
120121
}
121-
#ifdef DEBUG
122+
122123
// Add a label for checking the size of the code used for returning.
123124
Label check_exit_codesize;
124125
masm_->bind(&check_exit_codesize);
125-
#endif
126+
127+
// Calculate the exact length of the return sequence and make sure that
128+
// the constant pool is not emitted inside of the return sequence.
129+
int num_parameters = function_->scope()->num_parameters();
130+
int32_t sp_delta = (num_parameters + 1) * kPointerSize;
131+
int return_sequence_length = Debug::kARMJSReturnSequenceLength;
132+
if (!masm_->ImmediateFitsAddrMode1Instruction(sp_delta)) {
133+
// Additional mov instruction generated.
134+
return_sequence_length++;
135+
}
136+
masm_->BlockConstPoolFor(return_sequence_length);
137+
126138
CodeGenerator::RecordPositions(masm_, position);
127139
__ RecordJSReturn();
128140
__ mov(sp, fp);
129141
__ ldm(ia_w, sp, fp.bit() | lr.bit());
130-
int num_parameters = function_->scope()->num_parameters();
131-
__ add(sp, sp, Operand((num_parameters + 1) * kPointerSize));
142+
__ add(sp, sp, Operand(sp_delta));
132143
__ Jump(lr);
133-
#ifdef DEBUG
144+
134145
// Check that the size of the code used for returning matches what is
135146
// expected by the debugger. The add instruction above is an addressing
136147
// mode 1 instruction where there are restrictions on which immediate values
137148
// can be encoded in the instruction and which immediate values requires
138149
// use of an additional instruction for moving the immediate to a temporary
139150
// register.
140-
int expected_return_sequence_length = CodeGenerator::kJSReturnSequenceLength;
141-
if (!masm_->ImmediateFitsAddrMode1Instruction((num_parameters + 1) *
142-
kPointerSize)) {
143-
// Additional mov instruction generated.
144-
expected_return_sequence_length++;
145-
}
146151
ASSERT_EQ(expected_return_sequence_length,
147152
masm_->InstructionsGeneratedSince(&check_exit_codesize));
148-
#endif
149153
}
150154
}
151155

src/debug.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -377,6 +377,8 @@ class Debug {
377377
static const int kX64CallInstructionLength = 13;
378378
static const int kX64JSReturnSequenceLength = 13;
379379

380+
static const int kARMJSReturnSequenceLength = 4;
381+
380382
// Code generator routines.
381383
static void GenerateLoadICDebugBreak(MacroAssembler* masm);
382384
static void GenerateStoreICDebugBreak(MacroAssembler* masm);
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
// Copyright 2009 the V8 project authors. All rights reserved.
2+
// Redistribution and use in source and binary forms, with or without
3+
// modification, are permitted provided that the following conditions are
4+
// met:
5+
//
6+
// * Redistributions of source code must retain the above copyright
7+
// notice, this list of conditions and the following disclaimer.
8+
// * Redistributions in binary form must reproduce the above
9+
// copyright notice, this list of conditions and the following
10+
// disclaimer in the documentation and/or other materials provided
11+
// with the distribution.
12+
// * Neither the name of Google Inc. nor the names of its
13+
// contributors may be used to endorse or promote products derived
14+
// from this software without specific prior written permission.
15+
//
16+
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17+
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18+
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19+
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20+
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21+
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22+
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23+
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24+
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25+
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26+
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27+
28+
// See: http://code.google.com/p/v8/issues/detail?id=491
29+
// This should not hit any asserts in debug mode on ARM.
30+
31+
function function_with_n_strings(n) {
32+
var source = '(function f(){';
33+
for (var i = 0; i < n; i++) {
34+
if (i != 0) source += ';';
35+
source += '"x"';
36+
}
37+
source += '})()';
38+
eval(source);
39+
}
40+
41+
var i;
42+
for (i = 500; i < 600; i++) {
43+
function_with_n_strings(i);
44+
}
45+
for (i = 1100; i < 1200; i++) {
46+
function_with_n_strings(i);
47+
}

0 commit comments

Comments
 (0)