Improve positions recording for calls.

Review URL: http://codereview.chromium.org/4469002

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@5768 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
vegorov@chromium.org 2010-11-04 15:12:03 +00:00
parent 455cfe5932
commit 746d72420c
20 changed files with 493 additions and 369 deletions

View File

@ -317,7 +317,8 @@ static const Instr kLdrStrOffsetMask = 0x00000fff;
static const int kMinimalBufferSize = 4*KB; static const int kMinimalBufferSize = 4*KB;
static byte* spare_buffer_ = NULL; static byte* spare_buffer_ = NULL;
Assembler::Assembler(void* buffer, int buffer_size) { Assembler::Assembler(void* buffer, int buffer_size)
: positions_recorder_(this) {
if (buffer == NULL) { if (buffer == NULL) {
// Do our own buffer management. // Do our own buffer management.
if (buffer_size <= kMinimalBufferSize) { if (buffer_size <= kMinimalBufferSize) {
@ -354,10 +355,6 @@ Assembler::Assembler(void* buffer, int buffer_size) {
no_const_pool_before_ = 0; no_const_pool_before_ = 0;
last_const_pool_end_ = 0; last_const_pool_end_ = 0;
last_bound_pos_ = 0; last_bound_pos_ = 0;
current_statement_position_ = RelocInfo::kNoPosition;
current_position_ = RelocInfo::kNoPosition;
written_statement_position_ = current_statement_position_;
written_position_ = current_position_;
} }
@ -999,7 +996,7 @@ void Assembler::bl(int branch_offset, Condition cond) {
void Assembler::blx(int branch_offset) { // v5 and above void Assembler::blx(int branch_offset) { // v5 and above
WriteRecordedPositions(); positions_recorder()->WriteRecordedPositions();
ASSERT((branch_offset & 1) == 0); ASSERT((branch_offset & 1) == 0);
int h = ((branch_offset & 2) >> 1)*B24; int h = ((branch_offset & 2) >> 1)*B24;
int imm24 = branch_offset >> 2; int imm24 = branch_offset >> 2;
@ -1009,14 +1006,14 @@ void Assembler::blx(int branch_offset) { // v5 and above
void Assembler::blx(Register target, Condition cond) { // v5 and above void Assembler::blx(Register target, Condition cond) { // v5 and above
WriteRecordedPositions(); positions_recorder()->WriteRecordedPositions();
ASSERT(!target.is(pc)); ASSERT(!target.is(pc));
emit(cond | B24 | B21 | 15*B16 | 15*B12 | 15*B8 | 3*B4 | target.code()); emit(cond | B24 | B21 | 15*B16 | 15*B12 | 15*B8 | 3*B4 | target.code());
} }
void Assembler::bx(Register target, Condition cond) { // v5 and above, plus v4t void Assembler::bx(Register target, Condition cond) { // v5 and above, plus v4t
WriteRecordedPositions(); positions_recorder()->WriteRecordedPositions();
ASSERT(!target.is(pc)); // use of pc is actually allowed, but discouraged ASSERT(!target.is(pc)); // use of pc is actually allowed, but discouraged
emit(cond | B24 | B21 | 15*B16 | 15*B12 | 15*B8 | B4 | target.code()); emit(cond | B24 | B21 | 15*B16 | 15*B12 | 15*B8 | B4 | target.code());
} }
@ -1114,7 +1111,7 @@ void Assembler::orr(Register dst, Register src1, const Operand& src2,
void Assembler::mov(Register dst, const Operand& src, SBit s, Condition cond) { void Assembler::mov(Register dst, const Operand& src, SBit s, Condition cond) {
if (dst.is(pc)) { if (dst.is(pc)) {
WriteRecordedPositions(); positions_recorder()->WriteRecordedPositions();
} }
// Don't allow nop instructions in the form mov rn, rn to be generated using // Don't allow nop instructions in the form mov rn, rn to be generated using
// the mov instruction. They must be generated using nop(int) // the mov instruction. They must be generated using nop(int)
@ -1359,7 +1356,7 @@ void Assembler::msr(SRegisterFieldMask fields, const Operand& src,
// Load/Store instructions. // Load/Store instructions.
void Assembler::ldr(Register dst, const MemOperand& src, Condition cond) { void Assembler::ldr(Register dst, const MemOperand& src, Condition cond) {
if (dst.is(pc)) { if (dst.is(pc)) {
WriteRecordedPositions(); positions_recorder()->WriteRecordedPositions();
} }
addrmod2(cond | B26 | L, dst, src); addrmod2(cond | B26 | L, dst, src);
@ -2377,14 +2374,14 @@ void Assembler::BlockConstPoolFor(int instructions) {
// Debugging. // Debugging.
void Assembler::RecordJSReturn() { void Assembler::RecordJSReturn() {
WriteRecordedPositions(); positions_recorder()->WriteRecordedPositions();
CheckBuffer(); CheckBuffer();
RecordRelocInfo(RelocInfo::JS_RETURN); RecordRelocInfo(RelocInfo::JS_RETURN);
} }
void Assembler::RecordDebugBreakSlot() { void Assembler::RecordDebugBreakSlot() {
WriteRecordedPositions(); positions_recorder()->WriteRecordedPositions();
CheckBuffer(); CheckBuffer();
RecordRelocInfo(RelocInfo::DEBUG_BREAK_SLOT); RecordRelocInfo(RelocInfo::DEBUG_BREAK_SLOT);
} }
@ -2398,47 +2395,6 @@ void Assembler::RecordComment(const char* msg) {
} }
void Assembler::RecordPosition(int pos) {
if (pos == RelocInfo::kNoPosition) return;
ASSERT(pos >= 0);
current_position_ = pos;
}
void Assembler::RecordStatementPosition(int pos) {
if (pos == RelocInfo::kNoPosition) return;
ASSERT(pos >= 0);
current_statement_position_ = pos;
}
bool Assembler::WriteRecordedPositions() {
bool written = false;
// Write the statement position if it is different from what was written last
// time.
if (current_statement_position_ != written_statement_position_) {
CheckBuffer();
RecordRelocInfo(RelocInfo::STATEMENT_POSITION, current_statement_position_);
written_statement_position_ = current_statement_position_;
written = true;
}
// Write the position if it is different from what was written last time and
// also different from the written statement position.
if (current_position_ != written_position_ &&
current_position_ != written_statement_position_) {
CheckBuffer();
RecordRelocInfo(RelocInfo::POSITION, current_position_);
written_position_ = current_position_;
written = true;
}
// Return whether something was written.
return written;
}
void Assembler::GrowBuffer() { void Assembler::GrowBuffer() {
if (!own_buffer_) FATAL("external code buffer is too small"); if (!own_buffer_) FATAL("external code buffer is too small");

View File

@ -1117,13 +1117,9 @@ class Assembler : public Malloced {
// Use --debug_code to enable. // Use --debug_code to enable.
void RecordComment(const char* msg); void RecordComment(const char* msg);
void RecordPosition(int pos);
void RecordStatementPosition(int pos);
bool WriteRecordedPositions();
int pc_offset() const { return pc_ - buffer_; } int pc_offset() const { return pc_ - buffer_; }
int current_position() const { return current_position_; }
int current_statement_position() const { return current_statement_position_; } PositionsRecorder* positions_recorder() { return &positions_recorder_; }
bool can_peephole_optimize(int instructions) { bool can_peephole_optimize(int instructions) {
if (!FLAG_peephole_optimization) return false; if (!FLAG_peephole_optimization) return false;
@ -1259,12 +1255,6 @@ class Assembler : public Malloced {
// The bound position, before this we cannot do instruction elimination. // The bound position, before this we cannot do instruction elimination.
int last_bound_pos_; int last_bound_pos_;
// source position information
int current_position_;
int current_statement_position_;
int written_position_;
int written_statement_position_;
// Code emission // Code emission
inline void CheckBuffer(); inline void CheckBuffer();
void GrowBuffer(); void GrowBuffer();
@ -1290,8 +1280,21 @@ class Assembler : public Malloced {
friend class RelocInfo; friend class RelocInfo;
friend class CodePatcher; friend class CodePatcher;
friend class BlockConstPoolScope; friend class BlockConstPoolScope;
PositionsRecorder positions_recorder_;
friend class PositionsRecorder;
friend class EnsureSpace;
}; };
class EnsureSpace BASE_EMBEDDED {
public:
EnsureSpace(Assembler* assembler) {
assembler->CheckBuffer();
}
};
} } // namespace v8::internal } } // namespace v8::internal
#endif // V8_ARM_ASSEMBLER_ARM_H_ #endif // V8_ARM_ASSEMBLER_ARM_H_

View File

@ -1688,12 +1688,14 @@ void FullCodeGenerator::EmitCallWithIC(Call* expr,
// Code common for calls using the IC. // Code common for calls using the IC.
ZoneList<Expression*>* args = expr->arguments(); ZoneList<Expression*>* args = expr->arguments();
int arg_count = args->length(); int arg_count = args->length();
for (int i = 0; i < arg_count; i++) { { PreserveStatementPositionScope scope(masm()->positions_recorder());
VisitForStackValue(args->at(i)); for (int i = 0; i < arg_count; i++) {
VisitForStackValue(args->at(i));
}
__ mov(r2, Operand(name));
} }
__ mov(r2, Operand(name));
// Record source position for debugger. // Record source position for debugger.
SetSourcePosition(expr->position()); SetSourcePosition(expr->position(), FORCED_POSITION);
// Call the IC initialization code. // Call the IC initialization code.
InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP;
Handle<Code> ic = CodeGenerator::ComputeCallInitialize(arg_count, in_loop); Handle<Code> ic = CodeGenerator::ComputeCallInitialize(arg_count, in_loop);
@ -1710,13 +1712,15 @@ void FullCodeGenerator::EmitKeyedCallWithIC(Call* expr,
// Code common for calls using the IC. // Code common for calls using the IC.
ZoneList<Expression*>* args = expr->arguments(); ZoneList<Expression*>* args = expr->arguments();
int arg_count = args->length(); int arg_count = args->length();
for (int i = 0; i < arg_count; i++) { { PreserveStatementPositionScope scope(masm()->positions_recorder());
VisitForStackValue(args->at(i)); for (int i = 0; i < arg_count; i++) {
VisitForStackValue(args->at(i));
}
VisitForAccumulatorValue(key);
__ mov(r2, r0);
} }
VisitForAccumulatorValue(key);
__ mov(r2, r0);
// Record source position for debugger. // Record source position for debugger.
SetSourcePosition(expr->position()); SetSourcePosition(expr->position(), FORCED_POSITION);
// Call the IC initialization code. // Call the IC initialization code.
InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP;
Handle<Code> ic = CodeGenerator::ComputeKeyedCallInitialize(arg_count, Handle<Code> ic = CodeGenerator::ComputeKeyedCallInitialize(arg_count,
@ -1732,11 +1736,13 @@ void FullCodeGenerator::EmitCallWithStub(Call* expr) {
// Code common for calls using the call stub. // Code common for calls using the call stub.
ZoneList<Expression*>* args = expr->arguments(); ZoneList<Expression*>* args = expr->arguments();
int arg_count = args->length(); int arg_count = args->length();
for (int i = 0; i < arg_count; i++) { { PreserveStatementPositionScope scope(masm()->positions_recorder());
VisitForStackValue(args->at(i)); for (int i = 0; i < arg_count; i++) {
VisitForStackValue(args->at(i));
}
} }
// Record source position for debugger. // Record source position for debugger.
SetSourcePosition(expr->position()); SetSourcePosition(expr->position(), FORCED_POSITION);
InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP;
CallFunctionStub stub(arg_count, in_loop, RECEIVER_MIGHT_BE_VALUE); CallFunctionStub stub(arg_count, in_loop, RECEIVER_MIGHT_BE_VALUE);
__ CallStub(&stub); __ CallStub(&stub);
@ -1756,41 +1762,46 @@ void FullCodeGenerator::VisitCall(Call* expr) {
// resolve the function we need to call and the receiver of the // resolve the function we need to call and the receiver of the
// call. Then we call the resolved function using the given // call. Then we call the resolved function using the given
// arguments. // arguments.
VisitForStackValue(fun);
__ LoadRoot(r2, Heap::kUndefinedValueRootIndex);
__ push(r2); // Reserved receiver slot.
// Push the arguments.
ZoneList<Expression*>* args = expr->arguments(); ZoneList<Expression*>* args = expr->arguments();
int arg_count = args->length(); int arg_count = args->length();
for (int i = 0; i < arg_count; i++) {
VisitForStackValue(args->at(i));
}
// Push copy of the function - found below the arguments. { PreserveStatementPositionScope pos_scope(masm()->positions_recorder());
__ ldr(r1, MemOperand(sp, (arg_count + 1) * kPointerSize));
__ push(r1);
// Push copy of the first argument or undefined if it doesn't exist. VisitForStackValue(fun);
if (arg_count > 0) { __ LoadRoot(r2, Heap::kUndefinedValueRootIndex);
__ ldr(r1, MemOperand(sp, arg_count * kPointerSize)); __ push(r2); // Reserved receiver slot.
// Push the arguments.
for (int i = 0; i < arg_count; i++) {
VisitForStackValue(args->at(i));
}
// Push copy of the function - found below the arguments.
__ ldr(r1, MemOperand(sp, (arg_count + 1) * kPointerSize));
__ push(r1); __ push(r1);
} else {
__ push(r2); // Push copy of the first argument or undefined if it doesn't exist.
if (arg_count > 0) {
__ ldr(r1, MemOperand(sp, arg_count * kPointerSize));
__ push(r1);
} else {
__ push(r2);
}
// Push the receiver of the enclosing function and do runtime call.
__ ldr(r1,
MemOperand(fp, (2 + scope()->num_parameters()) * kPointerSize));
__ push(r1);
__ CallRuntime(Runtime::kResolvePossiblyDirectEval, 3);
// The runtime call returns a pair of values in r0 (function) and
// r1 (receiver). Touch up the stack with the right values.
__ str(r0, MemOperand(sp, (arg_count + 1) * kPointerSize));
__ str(r1, MemOperand(sp, arg_count * kPointerSize));
} }
// Push the receiver of the enclosing function and do runtime call.
__ ldr(r1, MemOperand(fp, (2 + scope()->num_parameters()) * kPointerSize));
__ push(r1);
__ CallRuntime(Runtime::kResolvePossiblyDirectEval, 3);
// The runtime call returns a pair of values in r0 (function) and
// r1 (receiver). Touch up the stack with the right values.
__ str(r0, MemOperand(sp, (arg_count + 1) * kPointerSize));
__ str(r1, MemOperand(sp, arg_count * kPointerSize));
// Record source position for debugger. // Record source position for debugger.
SetSourcePosition(expr->position()); SetSourcePosition(expr->position(), FORCED_POSITION);
InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP;
CallFunctionStub stub(arg_count, in_loop, RECEIVER_MIGHT_BE_VALUE); CallFunctionStub stub(arg_count, in_loop, RECEIVER_MIGHT_BE_VALUE);
__ CallStub(&stub); __ CallStub(&stub);
@ -1807,12 +1818,14 @@ void FullCodeGenerator::VisitCall(Call* expr) {
// Call to a lookup slot (dynamically introduced variable). // Call to a lookup slot (dynamically introduced variable).
Label slow, done; Label slow, done;
// Generate code for loading from variables potentially shadowed { PreserveStatementPositionScope scope(masm()->positions_recorder());
// by eval-introduced variables. // Generate code for loading from variables potentially shadowed
EmitDynamicLoadFromSlotFastCase(var->AsSlot(), // by eval-introduced variables.
NOT_INSIDE_TYPEOF, EmitDynamicLoadFromSlotFastCase(var->AsSlot(),
&slow, NOT_INSIDE_TYPEOF,
&done); &slow,
&done);
}
__ bind(&slow); __ bind(&slow);
// Call the runtime to find the function to call (returned in r0) // Call the runtime to find the function to call (returned in r0)
@ -1846,17 +1859,23 @@ void FullCodeGenerator::VisitCall(Call* expr) {
Literal* key = prop->key()->AsLiteral(); Literal* key = prop->key()->AsLiteral();
if (key != NULL && key->handle()->IsSymbol()) { if (key != NULL && key->handle()->IsSymbol()) {
// Call to a named property, use call IC. // Call to a named property, use call IC.
VisitForStackValue(prop->obj()); { PreserveStatementPositionScope scope(masm()->positions_recorder());
VisitForStackValue(prop->obj());
}
EmitCallWithIC(expr, key->handle(), RelocInfo::CODE_TARGET); EmitCallWithIC(expr, key->handle(), RelocInfo::CODE_TARGET);
} else { } else {
// Call to a keyed property. // Call to a keyed property.
// For a synthetic property use keyed load IC followed by function call, // For a synthetic property use keyed load IC followed by function call,
// for a regular property use keyed CallIC. // for a regular property use keyed CallIC.
VisitForStackValue(prop->obj()); { PreserveStatementPositionScope scope(masm()->positions_recorder());
VisitForStackValue(prop->obj());
}
if (prop->is_synthetic()) { if (prop->is_synthetic()) {
VisitForAccumulatorValue(prop->key()); { PreserveStatementPositionScope scope(masm()->positions_recorder());
VisitForAccumulatorValue(prop->key());
}
// Record source code position for IC call. // Record source code position for IC call.
SetSourcePosition(prop->position()); SetSourcePosition(prop->position(), FORCED_POSITION);
__ pop(r1); // We do not need to keep the receiver. __ pop(r1); // We do not need to keep the receiver.
Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize));
@ -1879,7 +1898,10 @@ void FullCodeGenerator::VisitCall(Call* expr) {
loop_depth() == 0) { loop_depth() == 0) {
lit->set_try_full_codegen(true); lit->set_try_full_codegen(true);
} }
VisitForStackValue(fun);
{ PreserveStatementPositionScope scope(masm()->positions_recorder());
VisitForStackValue(fun);
}
// Load global receiver object. // Load global receiver object.
__ ldr(r1, CodeGenerator::GlobalObject()); __ ldr(r1, CodeGenerator::GlobalObject());
__ ldr(r1, FieldMemOperand(r1, GlobalObject::kGlobalReceiverOffset)); __ ldr(r1, FieldMemOperand(r1, GlobalObject::kGlobalReceiverOffset));

View File

@ -129,7 +129,7 @@ void MacroAssembler::Call(intptr_t target, RelocInfo::Mode rmode,
// address is loaded. The mov method will automatically record // address is loaded. The mov method will automatically record
// positions when pc is the target, since this is not the case here // positions when pc is the target, since this is not the case here
// we have to do it explicitly. // we have to do it explicitly.
WriteRecordedPositions(); positions_recorder()->WriteRecordedPositions();
mov(ip, Operand(target, rmode), LeaveCC, cond); mov(ip, Operand(target, rmode), LeaveCC, cond);
blx(ip, cond); blx(ip, cond);

View File

@ -804,4 +804,53 @@ ExternalReference ExternalReference::debug_step_in_fp_address() {
} }
#endif #endif
void PositionsRecorder::RecordPosition(int pos,
PositionRecordingType recording_type) {
ASSERT(pos != RelocInfo::kNoPosition);
ASSERT(pos >= 0);
current_position_ = pos;
current_position_recording_type_ = recording_type;
}
void PositionsRecorder::RecordStatementPosition(int pos) {
ASSERT(pos != RelocInfo::kNoPosition);
ASSERT(pos >= 0);
current_statement_position_ = pos;
}
bool PositionsRecorder::WriteRecordedPositions() {
bool written = false;
// Write the statement position if it is different from what was written last
// time.
if (current_statement_position_ != written_statement_position_) {
EnsureSpace ensure_space(assembler_);
assembler_->RecordRelocInfo(RelocInfo::STATEMENT_POSITION,
current_statement_position_);
written_statement_position_ = current_statement_position_;
written = true;
}
// Write the position if it is different from what was written last time and
// also different from the written statement position or was forced.
if (current_position_ != written_position_ &&
(current_position_ != current_statement_position_ || !written) &&
(current_position_ != written_statement_position_
|| current_position_recording_type_ == FORCED_POSITION)) {
EnsureSpace ensure_space(assembler_);
assembler_->RecordRelocInfo(RelocInfo::POSITION, current_position_);
written_position_ = current_position_;
written = true;
}
current_position_recording_type_ = NORMAL_POSITION;
// Return whether something was written.
return written;
}
} } // namespace v8::internal } } // namespace v8::internal

View File

@ -584,6 +584,67 @@ class ExternalReference BASE_EMBEDDED {
}; };
// -----------------------------------------------------------------------------
// Position recording support
enum PositionRecordingType { FORCED_POSITION, NORMAL_POSITION };
class PositionsRecorder BASE_EMBEDDED {
public:
explicit PositionsRecorder(Assembler* assembler)
: assembler_(assembler),
current_position_(RelocInfo::kNoPosition),
current_position_recording_type_(NORMAL_POSITION),
written_position_(RelocInfo::kNoPosition),
current_statement_position_(RelocInfo::kNoPosition),
written_statement_position_(RelocInfo::kNoPosition) { }
// Set current position to pos. If recording_type is FORCED_POSITION then
// WriteRecordedPositions will write this position even if it is equal to
// statement position previously written for another pc.
void RecordPosition(int pos,
PositionRecordingType recording_type = NORMAL_POSITION);
// Set current statement position to pos.
void RecordStatementPosition(int pos);
// Write recorded positions to relocation information.
bool WriteRecordedPositions();
int current_position() const { return current_position_; }
int current_statement_position() const { return current_statement_position_; }
private:
Assembler* assembler_;
int current_position_;
PositionRecordingType current_position_recording_type_;
int written_position_;
int current_statement_position_;
int written_statement_position_;
};
class PreserveStatementPositionScope BASE_EMBEDDED {
public:
PreserveStatementPositionScope(PositionsRecorder* positions_recorder)
: positions_recorder_(positions_recorder),
statement_position_(positions_recorder->current_statement_position()) {}
~PreserveStatementPositionScope() {
if (statement_position_ != RelocInfo::kNoPosition) {
positions_recorder_->RecordStatementPosition(statement_position_);
}
}
private:
PositionsRecorder* positions_recorder_;
int statement_position_;
};
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// Utility functions // Utility functions

View File

@ -70,9 +70,10 @@ void CodeGenerator::ProcessDeferred() {
DeferredCode* code = deferred_.RemoveLast(); DeferredCode* code = deferred_.RemoveLast();
ASSERT(masm_ == code->masm()); ASSERT(masm_ == code->masm());
// Record position of deferred code stub. // Record position of deferred code stub.
masm_->RecordStatementPosition(code->statement_position()); masm_->positions_recorder()->RecordStatementPosition(
code->statement_position());
if (code->position() != RelocInfo::kNoPosition) { if (code->position() != RelocInfo::kNoPosition) {
masm_->RecordPosition(code->position()); masm_->positions_recorder()->RecordPosition(code->position());
} }
// Generate the code. // Generate the code.
Comment cmnt(masm_, code->comment()); Comment cmnt(masm_, code->comment());
@ -402,10 +403,10 @@ bool CodeGenerator::RecordPositions(MacroAssembler* masm,
int pos, int pos,
bool right_here) { bool right_here) {
if (pos != RelocInfo::kNoPosition) { if (pos != RelocInfo::kNoPosition) {
masm->RecordStatementPosition(pos); masm->positions_recorder()->RecordStatementPosition(pos);
masm->RecordPosition(pos); masm->positions_recorder()->RecordPosition(pos);
if (right_here) { if (right_here) {
return masm->WriteRecordedPositions(); return masm->positions_recorder()->WriteRecordedPositions();
} }
} }
return false; return false;
@ -435,7 +436,7 @@ void CodeGenerator::CodeForDoWhileConditionPosition(DoWhileStatement* stmt) {
void CodeGenerator::CodeForSourcePosition(int pos) { void CodeGenerator::CodeForSourcePosition(int pos) {
if (FLAG_debug_info && pos != RelocInfo::kNoPosition) { if (FLAG_debug_info && pos != RelocInfo::kNoPosition) {
masm()->RecordPosition(pos); masm()->positions_recorder()->RecordPosition(pos);
} }
} }

View File

@ -563,9 +563,10 @@ void FullCodeGenerator::SetStatementPosition(int pos) {
} }
void FullCodeGenerator::SetSourcePosition(int pos) { void FullCodeGenerator::SetSourcePosition(
int pos, PositionRecordingType recording_type) {
if (FLAG_debug_info && pos != RelocInfo::kNoPosition) { if (FLAG_debug_info && pos != RelocInfo::kNoPosition) {
masm_->RecordPosition(pos); masm_->positions_recorder()->RecordPosition(pos, recording_type);
} }
} }

View File

@ -423,7 +423,9 @@ class FullCodeGenerator: public AstVisitor {
void SetStatementPosition(Statement* stmt); void SetStatementPosition(Statement* stmt);
void SetExpressionPosition(Expression* expr, int pos); void SetExpressionPosition(Expression* expr, int pos);
void SetStatementPosition(int pos); void SetStatementPosition(int pos);
void SetSourcePosition(int pos); void SetSourcePosition(
int pos,
PositionRecordingType recording_type = NORMAL_POSITION);
// Non-local control flow support. // Non-local control flow support.
void EnterFinallyBlock(); void EnterFinallyBlock();

View File

@ -298,7 +298,8 @@ static void InitCoverageLog();
// Spare buffer. // Spare buffer.
byte* Assembler::spare_buffer_ = NULL; byte* Assembler::spare_buffer_ = NULL;
Assembler::Assembler(void* buffer, int buffer_size) { Assembler::Assembler(void* buffer, int buffer_size)
: positions_recorder_(this) {
if (buffer == NULL) { if (buffer == NULL) {
// Do our own buffer management. // Do our own buffer management.
if (buffer_size <= kMinimalBufferSize) { if (buffer_size <= kMinimalBufferSize) {
@ -339,10 +340,6 @@ Assembler::Assembler(void* buffer, int buffer_size) {
reloc_info_writer.Reposition(buffer_ + buffer_size, pc_); reloc_info_writer.Reposition(buffer_ + buffer_size, pc_);
last_pc_ = NULL; last_pc_ = NULL;
current_statement_position_ = RelocInfo::kNoPosition;
current_position_ = RelocInfo::kNoPosition;
written_statement_position_ = current_statement_position_;
written_position_ = current_position_;
#ifdef GENERATED_CODE_COVERAGE #ifdef GENERATED_CODE_COVERAGE
InitCoverageLog(); InitCoverageLog();
#endif #endif
@ -1581,7 +1578,7 @@ void Assembler::call(const Operand& adr) {
void Assembler::call(Handle<Code> code, RelocInfo::Mode rmode) { void Assembler::call(Handle<Code> code, RelocInfo::Mode rmode) {
WriteRecordedPositions(); positions_recorder()->WriteRecordedPositions();
EnsureSpace ensure_space(this); EnsureSpace ensure_space(this);
last_pc_ = pc_; last_pc_ = pc_;
ASSERT(RelocInfo::IsCodeTarget(rmode)); ASSERT(RelocInfo::IsCodeTarget(rmode));
@ -2464,14 +2461,14 @@ void Assembler::Print() {
void Assembler::RecordJSReturn() { void Assembler::RecordJSReturn() {
WriteRecordedPositions(); positions_recorder()->WriteRecordedPositions();
EnsureSpace ensure_space(this); EnsureSpace ensure_space(this);
RecordRelocInfo(RelocInfo::JS_RETURN); RecordRelocInfo(RelocInfo::JS_RETURN);
} }
void Assembler::RecordDebugBreakSlot() { void Assembler::RecordDebugBreakSlot() {
WriteRecordedPositions(); positions_recorder()->WriteRecordedPositions();
EnsureSpace ensure_space(this); EnsureSpace ensure_space(this);
RecordRelocInfo(RelocInfo::DEBUG_BREAK_SLOT); RecordRelocInfo(RelocInfo::DEBUG_BREAK_SLOT);
} }
@ -2485,47 +2482,6 @@ void Assembler::RecordComment(const char* msg) {
} }
void Assembler::RecordPosition(int pos) {
ASSERT(pos != RelocInfo::kNoPosition);
ASSERT(pos >= 0);
current_position_ = pos;
}
void Assembler::RecordStatementPosition(int pos) {
ASSERT(pos != RelocInfo::kNoPosition);
ASSERT(pos >= 0);
current_statement_position_ = pos;
}
bool Assembler::WriteRecordedPositions() {
bool written = false;
// Write the statement position if it is different from what was written last
// time.
if (current_statement_position_ != written_statement_position_) {
EnsureSpace ensure_space(this);
RecordRelocInfo(RelocInfo::STATEMENT_POSITION, current_statement_position_);
written_statement_position_ = current_statement_position_;
written = true;
}
// Write the position if it is different from what was written last time and
// also different from the written statement position.
if (current_position_ != written_position_ &&
current_position_ != written_statement_position_) {
EnsureSpace ensure_space(this);
RecordRelocInfo(RelocInfo::POSITION, current_position_);
written_position_ = current_position_;
written = true;
}
// Return whether something was written.
return written;
}
void Assembler::GrowBuffer() { void Assembler::GrowBuffer() {
ASSERT(overflow()); ASSERT(overflow());
if (!own_buffer_) FATAL("external code buffer is too small"); if (!own_buffer_) FATAL("external code buffer is too small");

View File

@ -847,17 +847,11 @@ class Assembler : public Malloced {
// Use --debug_code to enable. // Use --debug_code to enable.
void RecordComment(const char* msg); void RecordComment(const char* msg);
void RecordPosition(int pos);
void RecordStatementPosition(int pos);
bool WriteRecordedPositions();
// Writes a single word of data in the code stream. // Writes a single word of data in the code stream.
// Used for inline tables, e.g., jump-tables. // Used for inline tables, e.g., jump-tables.
void dd(uint32_t data, RelocInfo::Mode reloc_info); void dd(uint32_t data, RelocInfo::Mode reloc_info);
int pc_offset() const { return pc_ - buffer_; } int pc_offset() const { return pc_ - buffer_; }
int current_statement_position() const { return current_statement_position_; }
int current_position() const { return current_position_; }
// Check if there is less than kGap bytes available in the buffer. // Check if there is less than kGap bytes available in the buffer.
// If this is the case, we need to grow the buffer before emitting // If this is the case, we need to grow the buffer before emitting
@ -869,6 +863,8 @@ class Assembler : public Malloced {
static bool IsNop(Address addr) { return *addr == 0x90; } static bool IsNop(Address addr) { return *addr == 0x90; }
PositionsRecorder* positions_recorder() { return &positions_recorder_; }
// Avoid overflows for displacements etc. // Avoid overflows for displacements etc.
static const int kMaximalBufferSize = 512*MB; static const int kMaximalBufferSize = 512*MB;
static const int kMinimalBufferSize = 4*KB; static const int kMinimalBufferSize = 4*KB;
@ -947,11 +943,9 @@ class Assembler : public Malloced {
// push-pop elimination // push-pop elimination
byte* last_pc_; byte* last_pc_;
// source position information PositionsRecorder positions_recorder_;
int current_statement_position_;
int current_position_; friend class PositionsRecorder;
int written_statement_position_;
int written_position_;
}; };

View File

@ -3734,7 +3734,7 @@ void CodeGenerator::VisitReturnStatement(ReturnStatement* node) {
CodeForStatementPosition(node); CodeForStatementPosition(node);
Load(node->expression()); Load(node->expression());
Result return_value = frame_->Pop(); Result return_value = frame_->Pop();
masm()->WriteRecordedPositions(); masm()->positions_recorder()->WriteRecordedPositions();
if (function_return_is_shadowed_) { if (function_return_is_shadowed_) {
function_return_.Jump(&return_value); function_return_.Jump(&return_value);
} else { } else {

View File

@ -1996,12 +1996,14 @@ void FullCodeGenerator::EmitCallWithIC(Call* expr,
// Code common for calls using the IC. // Code common for calls using the IC.
ZoneList<Expression*>* args = expr->arguments(); ZoneList<Expression*>* args = expr->arguments();
int arg_count = args->length(); int arg_count = args->length();
for (int i = 0; i < arg_count; i++) { { PreserveStatementPositionScope scope(masm()->positions_recorder());
VisitForStackValue(args->at(i)); for (int i = 0; i < arg_count; i++) {
VisitForStackValue(args->at(i));
}
__ Set(ecx, Immediate(name));
} }
__ Set(ecx, Immediate(name));
// Record source position of the IC call. // Record source position of the IC call.
SetSourcePosition(expr->position()); SetSourcePosition(expr->position(), FORCED_POSITION);
InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP;
Handle<Code> ic = CodeGenerator::ComputeCallInitialize(arg_count, in_loop); Handle<Code> ic = CodeGenerator::ComputeCallInitialize(arg_count, in_loop);
EmitCallIC(ic, mode); EmitCallIC(ic, mode);
@ -2017,13 +2019,15 @@ void FullCodeGenerator::EmitKeyedCallWithIC(Call* expr,
// Code common for calls using the IC. // Code common for calls using the IC.
ZoneList<Expression*>* args = expr->arguments(); ZoneList<Expression*>* args = expr->arguments();
int arg_count = args->length(); int arg_count = args->length();
for (int i = 0; i < arg_count; i++) { { PreserveStatementPositionScope scope(masm()->positions_recorder());
VisitForStackValue(args->at(i)); for (int i = 0; i < arg_count; i++) {
VisitForStackValue(args->at(i));
}
VisitForAccumulatorValue(key);
__ mov(ecx, eax);
} }
VisitForAccumulatorValue(key);
__ mov(ecx, eax);
// Record source position of the IC call. // Record source position of the IC call.
SetSourcePosition(expr->position()); SetSourcePosition(expr->position(), FORCED_POSITION);
InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP;
Handle<Code> ic = CodeGenerator::ComputeKeyedCallInitialize( Handle<Code> ic = CodeGenerator::ComputeKeyedCallInitialize(
arg_count, in_loop); arg_count, in_loop);
@ -2038,11 +2042,13 @@ void FullCodeGenerator::EmitCallWithStub(Call* expr) {
// Code common for calls using the call stub. // Code common for calls using the call stub.
ZoneList<Expression*>* args = expr->arguments(); ZoneList<Expression*>* args = expr->arguments();
int arg_count = args->length(); int arg_count = args->length();
for (int i = 0; i < arg_count; i++) { { PreserveStatementPositionScope scope(masm()->positions_recorder());
VisitForStackValue(args->at(i)); for (int i = 0; i < arg_count; i++) {
VisitForStackValue(args->at(i));
}
} }
// Record source position for debugger. // Record source position for debugger.
SetSourcePosition(expr->position()); SetSourcePosition(expr->position(), FORCED_POSITION);
InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP;
CallFunctionStub stub(arg_count, in_loop, RECEIVER_MIGHT_BE_VALUE); CallFunctionStub stub(arg_count, in_loop, RECEIVER_MIGHT_BE_VALUE);
__ CallStub(&stub); __ CallStub(&stub);
@ -2062,37 +2068,38 @@ void FullCodeGenerator::VisitCall(Call* expr) {
// resolve the function we need to call and the receiver of the // resolve the function we need to call and the receiver of the
// call. Then we call the resolved function using the given // call. Then we call the resolved function using the given
// arguments. // arguments.
VisitForStackValue(fun);
__ push(Immediate(Factory::undefined_value())); // Reserved receiver slot.
// Push the arguments.
ZoneList<Expression*>* args = expr->arguments(); ZoneList<Expression*>* args = expr->arguments();
int arg_count = args->length(); int arg_count = args->length();
for (int i = 0; i < arg_count; i++) { { PreserveStatementPositionScope pos_scope(masm()->positions_recorder());
VisitForStackValue(args->at(i)); VisitForStackValue(fun);
__ push(Immediate(Factory::undefined_value())); // Reserved receiver slot.
// Push the arguments.
for (int i = 0; i < arg_count; i++) {
VisitForStackValue(args->at(i));
}
// Push copy of the function - found below the arguments.
__ push(Operand(esp, (arg_count + 1) * kPointerSize));
// Push copy of the first argument or undefined if it doesn't exist.
if (arg_count > 0) {
__ push(Operand(esp, arg_count * kPointerSize));
} else {
__ push(Immediate(Factory::undefined_value()));
}
// Push the receiver of the enclosing function and do runtime call.
__ push(Operand(ebp, (2 + scope()->num_parameters()) * kPointerSize));
__ CallRuntime(Runtime::kResolvePossiblyDirectEval, 3);
// The runtime call returns a pair of values in eax (function) and
// edx (receiver). Touch up the stack with the right values.
__ mov(Operand(esp, (arg_count + 0) * kPointerSize), edx);
__ mov(Operand(esp, (arg_count + 1) * kPointerSize), eax);
} }
// Push copy of the function - found below the arguments.
__ push(Operand(esp, (arg_count + 1) * kPointerSize));
// Push copy of the first argument or undefined if it doesn't exist.
if (arg_count > 0) {
__ push(Operand(esp, arg_count * kPointerSize));
} else {
__ push(Immediate(Factory::undefined_value()));
}
// Push the receiver of the enclosing function and do runtime call.
__ push(Operand(ebp, (2 + scope()->num_parameters()) * kPointerSize));
__ CallRuntime(Runtime::kResolvePossiblyDirectEval, 3);
// The runtime call returns a pair of values in eax (function) and
// edx (receiver). Touch up the stack with the right values.
__ mov(Operand(esp, (arg_count + 0) * kPointerSize), edx);
__ mov(Operand(esp, (arg_count + 1) * kPointerSize), eax);
// Record source position for debugger. // Record source position for debugger.
SetSourcePosition(expr->position()); SetSourcePosition(expr->position(), FORCED_POSITION);
InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP;
CallFunctionStub stub(arg_count, in_loop, RECEIVER_MIGHT_BE_VALUE); CallFunctionStub stub(arg_count, in_loop, RECEIVER_MIGHT_BE_VALUE);
__ CallStub(&stub); __ CallStub(&stub);
@ -2108,12 +2115,14 @@ void FullCodeGenerator::VisitCall(Call* expr) {
// Call to a lookup slot (dynamically introduced variable). // Call to a lookup slot (dynamically introduced variable).
Label slow, done; Label slow, done;
// Generate code for loading from variables potentially shadowed { PreserveStatementPositionScope scope(masm()->positions_recorder());
// by eval-introduced variables. // Generate code for loading from variables potentially shadowed
EmitDynamicLoadFromSlotFastCase(var->AsSlot(), // by eval-introduced variables.
NOT_INSIDE_TYPEOF, EmitDynamicLoadFromSlotFastCase(var->AsSlot(),
&slow, NOT_INSIDE_TYPEOF,
&done); &slow,
&done);
}
__ bind(&slow); __ bind(&slow);
// Call the runtime to find the function to call (returned in eax) // Call the runtime to find the function to call (returned in eax)
@ -2152,11 +2161,15 @@ void FullCodeGenerator::VisitCall(Call* expr) {
// Call to a keyed property. // Call to a keyed property.
// For a synthetic property use keyed load IC followed by function call, // For a synthetic property use keyed load IC followed by function call,
// for a regular property use keyed EmitCallIC. // for a regular property use keyed EmitCallIC.
VisitForStackValue(prop->obj()); { PreserveStatementPositionScope scope(masm()->positions_recorder());
VisitForStackValue(prop->obj());
}
if (prop->is_synthetic()) { if (prop->is_synthetic()) {
VisitForAccumulatorValue(prop->key()); { PreserveStatementPositionScope scope(masm()->positions_recorder());
VisitForAccumulatorValue(prop->key());
}
// Record source code position for IC call. // Record source code position for IC call.
SetSourcePosition(prop->position()); SetSourcePosition(prop->position(), FORCED_POSITION);
__ pop(edx); // We do not need to keep the receiver. __ pop(edx); // We do not need to keep the receiver.
Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize));
@ -2181,7 +2194,9 @@ void FullCodeGenerator::VisitCall(Call* expr) {
loop_depth() == 0) { loop_depth() == 0) {
lit->set_try_full_codegen(true); lit->set_try_full_codegen(true);
} }
VisitForStackValue(fun); { PreserveStatementPositionScope scope(masm()->positions_recorder());
VisitForStackValue(fun);
}
// Load global receiver object. // Load global receiver object.
__ mov(ebx, CodeGenerator::GlobalObject()); __ mov(ebx, CodeGenerator::GlobalObject());
__ push(FieldOperand(ebx, GlobalObject::kGlobalReceiverOffset)); __ push(FieldOperand(ebx, GlobalObject::kGlobalReceiverOffset));

View File

@ -414,8 +414,9 @@ void BreakTarget::Branch(Condition cc, Hint hint) {
DeferredCode::DeferredCode() DeferredCode::DeferredCode()
: masm_(CodeGeneratorScope::Current()->masm()), : masm_(CodeGeneratorScope::Current()->masm()),
statement_position_(masm_->current_statement_position()), statement_position_(masm_->positions_recorder()->
position_(masm_->current_position()), current_statement_position()),
position_(masm_->positions_recorder()->current_position()),
frame_state_(CodeGeneratorScope::Current()->frame()) { frame_state_(CodeGeneratorScope::Current()->frame()) {
ASSERT(statement_position_ != RelocInfo::kNoPosition); ASSERT(statement_position_ != RelocInfo::kNoPosition);
ASSERT(position_ != RelocInfo::kNoPosition); ASSERT(position_ != RelocInfo::kNoPosition);

View File

@ -36,8 +36,9 @@ namespace internal {
DeferredCode::DeferredCode() DeferredCode::DeferredCode()
: masm_(CodeGeneratorScope::Current()->masm()), : masm_(CodeGeneratorScope::Current()->masm()),
statement_position_(masm_->current_statement_position()), statement_position_(masm_->positions_recorder()->
position_(masm_->current_position()), current_statement_position()),
position_(masm_->positions_recorder()->current_position()),
frame_state_(*CodeGeneratorScope::Current()->frame()) { frame_state_(*CodeGeneratorScope::Current()->frame()) {
ASSERT(statement_position_ != RelocInfo::kNoPosition); ASSERT(statement_position_ != RelocInfo::kNoPosition);
ASSERT(position_ != RelocInfo::kNoPosition); ASSERT(position_ != RelocInfo::kNoPosition);

View File

@ -296,7 +296,7 @@ static void InitCoverageLog();
byte* Assembler::spare_buffer_ = NULL; byte* Assembler::spare_buffer_ = NULL;
Assembler::Assembler(void* buffer, int buffer_size) Assembler::Assembler(void* buffer, int buffer_size)
: code_targets_(100) { : code_targets_(100), positions_recorder_(this) {
if (buffer == NULL) { if (buffer == NULL) {
// Do our own buffer management. // Do our own buffer management.
if (buffer_size <= kMinimalBufferSize) { if (buffer_size <= kMinimalBufferSize) {
@ -337,10 +337,7 @@ Assembler::Assembler(void* buffer, int buffer_size)
reloc_info_writer.Reposition(buffer_ + buffer_size, pc_); reloc_info_writer.Reposition(buffer_ + buffer_size, pc_);
last_pc_ = NULL; last_pc_ = NULL;
current_statement_position_ = RelocInfo::kNoPosition;
current_position_ = RelocInfo::kNoPosition;
written_statement_position_ = current_statement_position_;
written_position_ = current_position_;
#ifdef GENERATED_CODE_COVERAGE #ifdef GENERATED_CODE_COVERAGE
InitCoverageLog(); InitCoverageLog();
#endif #endif
@ -845,7 +842,7 @@ void Assembler::call(Label* L) {
void Assembler::call(Handle<Code> target, RelocInfo::Mode rmode) { void Assembler::call(Handle<Code> target, RelocInfo::Mode rmode) {
WriteRecordedPositions(); positions_recorder()->WriteRecordedPositions();
EnsureSpace ensure_space(this); EnsureSpace ensure_space(this);
last_pc_ = pc_; last_pc_ = pc_;
// 1110 1000 #32-bit disp. // 1110 1000 #32-bit disp.
@ -2935,14 +2932,14 @@ void Assembler::RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data) {
} }
void Assembler::RecordJSReturn() { void Assembler::RecordJSReturn() {
WriteRecordedPositions(); positions_recorder()->WriteRecordedPositions();
EnsureSpace ensure_space(this); EnsureSpace ensure_space(this);
RecordRelocInfo(RelocInfo::JS_RETURN); RecordRelocInfo(RelocInfo::JS_RETURN);
} }
void Assembler::RecordDebugBreakSlot() { void Assembler::RecordDebugBreakSlot() {
WriteRecordedPositions(); positions_recorder()->WriteRecordedPositions();
EnsureSpace ensure_space(this); EnsureSpace ensure_space(this);
RecordRelocInfo(RelocInfo::DEBUG_BREAK_SLOT); RecordRelocInfo(RelocInfo::DEBUG_BREAK_SLOT);
} }
@ -2956,47 +2953,6 @@ void Assembler::RecordComment(const char* msg) {
} }
void Assembler::RecordPosition(int pos) {
ASSERT(pos != RelocInfo::kNoPosition);
ASSERT(pos >= 0);
current_position_ = pos;
}
void Assembler::RecordStatementPosition(int pos) {
ASSERT(pos != RelocInfo::kNoPosition);
ASSERT(pos >= 0);
current_statement_position_ = pos;
}
bool Assembler::WriteRecordedPositions() {
bool written = false;
// Write the statement position if it is different from what was written last
// time.
if (current_statement_position_ != written_statement_position_) {
EnsureSpace ensure_space(this);
RecordRelocInfo(RelocInfo::STATEMENT_POSITION, current_statement_position_);
written_statement_position_ = current_statement_position_;
written = true;
}
// Write the position if it is different from what was written last time and
// also different from the written statement position.
if (current_position_ != written_position_ &&
current_position_ != written_statement_position_) {
EnsureSpace ensure_space(this);
RecordRelocInfo(RelocInfo::POSITION, current_position_);
written_position_ = current_position_;
written = true;
}
// Return whether something was written.
return written;
}
const int RelocInfo::kApplyMask = RelocInfo::kCodeTargetMask | const int RelocInfo::kApplyMask = RelocInfo::kCodeTargetMask |
1 << RelocInfo::INTERNAL_REFERENCE; 1 << RelocInfo::INTERNAL_REFERENCE;

View File

@ -1174,13 +1174,9 @@ class Assembler : public Malloced {
// Use --debug_code to enable. // Use --debug_code to enable.
void RecordComment(const char* msg); void RecordComment(const char* msg);
void RecordPosition(int pos);
void RecordStatementPosition(int pos);
bool WriteRecordedPositions();
int pc_offset() const { return static_cast<int>(pc_ - buffer_); } int pc_offset() const { return static_cast<int>(pc_ - buffer_); }
int current_statement_position() const { return current_statement_position_; }
int current_position() const { return current_position_; } PositionsRecorder* positions_recorder() { return &positions_recorder_; }
// Check if there is less than kGap bytes available in the buffer. // Check if there is less than kGap bytes available in the buffer.
// If this is the case, we need to grow the buffer before emitting // If this is the case, we need to grow the buffer before emitting
@ -1404,11 +1400,8 @@ class Assembler : public Malloced {
// push-pop elimination // push-pop elimination
byte* last_pc_; byte* last_pc_;
// source position information PositionsRecorder positions_recorder_;
int current_statement_position_; friend class PositionsRecorder;
int current_position_;
int written_statement_position_;
int written_position_;
}; };

View File

@ -2956,7 +2956,7 @@ void CodeGenerator::VisitReturnStatement(ReturnStatement* node) {
CodeForStatementPosition(node); CodeForStatementPosition(node);
Load(node->expression()); Load(node->expression());
Result return_value = frame_->Pop(); Result return_value = frame_->Pop();
masm()->WriteRecordedPositions(); masm()->positions_recorder()->WriteRecordedPositions();
if (function_return_is_shadowed_) { if (function_return_is_shadowed_) {
function_return_.Jump(&return_value); function_return_.Jump(&return_value);
} else { } else {

View File

@ -1717,12 +1717,14 @@ void FullCodeGenerator::EmitCallWithIC(Call* expr,
// Code common for calls using the IC. // Code common for calls using the IC.
ZoneList<Expression*>* args = expr->arguments(); ZoneList<Expression*>* args = expr->arguments();
int arg_count = args->length(); int arg_count = args->length();
for (int i = 0; i < arg_count; i++) { { PreserveStatementPositionScope scope(masm()->positions_recorder());
VisitForStackValue(args->at(i)); for (int i = 0; i < arg_count; i++) {
VisitForStackValue(args->at(i));
}
__ Move(rcx, name);
} }
__ Move(rcx, name);
// Record source position for debugger. // Record source position for debugger.
SetSourcePosition(expr->position()); SetSourcePosition(expr->position(), FORCED_POSITION);
// Call the IC initialization code. // Call the IC initialization code.
InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP;
Handle<Code> ic = CodeGenerator::ComputeCallInitialize(arg_count, Handle<Code> ic = CodeGenerator::ComputeCallInitialize(arg_count,
@ -1740,13 +1742,15 @@ void FullCodeGenerator::EmitKeyedCallWithIC(Call* expr,
// Code common for calls using the IC. // Code common for calls using the IC.
ZoneList<Expression*>* args = expr->arguments(); ZoneList<Expression*>* args = expr->arguments();
int arg_count = args->length(); int arg_count = args->length();
for (int i = 0; i < arg_count; i++) { { PreserveStatementPositionScope scope(masm()->positions_recorder());
VisitForStackValue(args->at(i)); for (int i = 0; i < arg_count; i++) {
VisitForStackValue(args->at(i));
}
VisitForAccumulatorValue(key);
__ movq(rcx, rax);
} }
VisitForAccumulatorValue(key);
__ movq(rcx, rax);
// Record source position for debugger. // Record source position for debugger.
SetSourcePosition(expr->position()); SetSourcePosition(expr->position(), FORCED_POSITION);
// Call the IC initialization code. // Call the IC initialization code.
InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP;
Handle<Code> ic = CodeGenerator::ComputeKeyedCallInitialize(arg_count, Handle<Code> ic = CodeGenerator::ComputeKeyedCallInitialize(arg_count,
@ -1762,11 +1766,13 @@ void FullCodeGenerator::EmitCallWithStub(Call* expr) {
// Code common for calls using the call stub. // Code common for calls using the call stub.
ZoneList<Expression*>* args = expr->arguments(); ZoneList<Expression*>* args = expr->arguments();
int arg_count = args->length(); int arg_count = args->length();
for (int i = 0; i < arg_count; i++) { { PreserveStatementPositionScope scope(masm()->positions_recorder());
VisitForStackValue(args->at(i)); for (int i = 0; i < arg_count; i++) {
VisitForStackValue(args->at(i));
}
} }
// Record source position for debugger. // Record source position for debugger.
SetSourcePosition(expr->position()); SetSourcePosition(expr->position(), FORCED_POSITION);
InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP;
CallFunctionStub stub(arg_count, in_loop, RECEIVER_MIGHT_BE_VALUE); CallFunctionStub stub(arg_count, in_loop, RECEIVER_MIGHT_BE_VALUE);
__ CallStub(&stub); __ CallStub(&stub);
@ -1787,37 +1793,39 @@ void FullCodeGenerator::VisitCall(Call* expr) {
// resolve the function we need to call and the receiver of the // resolve the function we need to call and the receiver of the
// call. The we call the resolved function using the given // call. The we call the resolved function using the given
// arguments. // arguments.
VisitForStackValue(fun);
__ PushRoot(Heap::kUndefinedValueRootIndex); // Reserved receiver slot.
// Push the arguments.
ZoneList<Expression*>* args = expr->arguments(); ZoneList<Expression*>* args = expr->arguments();
int arg_count = args->length(); int arg_count = args->length();
for (int i = 0; i < arg_count; i++) { { PreserveStatementPositionScope pos_scope(masm()->positions_recorder());
VisitForStackValue(args->at(i));
}
// Push copy of the function - found below the arguments. VisitForStackValue(fun);
__ push(Operand(rsp, (arg_count + 1) * kPointerSize)); __ PushRoot(Heap::kUndefinedValueRootIndex); // Reserved receiver slot.
// Push copy of the first argument or undefined if it doesn't exist. // Push the arguments.
if (arg_count > 0) { for (int i = 0; i < arg_count; i++) {
__ push(Operand(rsp, arg_count * kPointerSize)); VisitForStackValue(args->at(i));
} else { }
// Push copy of the function - found below the arguments.
__ push(Operand(rsp, (arg_count + 1) * kPointerSize));
// Push copy of the first argument or undefined if it doesn't exist.
if (arg_count > 0) {
__ push(Operand(rsp, arg_count * kPointerSize));
} else {
__ PushRoot(Heap::kUndefinedValueRootIndex); __ PushRoot(Heap::kUndefinedValueRootIndex);
}
// Push the receiver of the enclosing function and do runtime call.
__ push(Operand(rbp, (2 + scope()->num_parameters()) * kPointerSize));
__ CallRuntime(Runtime::kResolvePossiblyDirectEval, 3);
// The runtime call returns a pair of values in rax (function) and
// rdx (receiver). Touch up the stack with the right values.
__ movq(Operand(rsp, (arg_count + 0) * kPointerSize), rdx);
__ movq(Operand(rsp, (arg_count + 1) * kPointerSize), rax);
} }
// Push the receiver of the enclosing function and do runtime call.
__ push(Operand(rbp, (2 + scope()->num_parameters()) * kPointerSize));
__ CallRuntime(Runtime::kResolvePossiblyDirectEval, 3);
// The runtime call returns a pair of values in rax (function) and
// rdx (receiver). Touch up the stack with the right values.
__ movq(Operand(rsp, (arg_count + 0) * kPointerSize), rdx);
__ movq(Operand(rsp, (arg_count + 1) * kPointerSize), rax);
// Record source position for debugger. // Record source position for debugger.
SetSourcePosition(expr->position()); SetSourcePosition(expr->position(), FORCED_POSITION);
InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP;
CallFunctionStub stub(arg_count, in_loop, RECEIVER_MIGHT_BE_VALUE); CallFunctionStub stub(arg_count, in_loop, RECEIVER_MIGHT_BE_VALUE);
__ CallStub(&stub); __ CallStub(&stub);
@ -1834,35 +1842,37 @@ void FullCodeGenerator::VisitCall(Call* expr) {
// Call to a lookup slot (dynamically introduced variable). // Call to a lookup slot (dynamically introduced variable).
Label slow, done; Label slow, done;
// Generate code for loading from variables potentially shadowed { PreserveStatementPositionScope scope(masm()->positions_recorder());
// by eval-introduced variables. // Generate code for loading from variables potentially shadowed
EmitDynamicLoadFromSlotFastCase(var->AsSlot(), // by eval-introduced variables.
NOT_INSIDE_TYPEOF, EmitDynamicLoadFromSlotFastCase(var->AsSlot(),
&slow, NOT_INSIDE_TYPEOF,
&done); &slow,
&done);
__ bind(&slow); __ bind(&slow);
// Call the runtime to find the function to call (returned in rax) // Call the runtime to find the function to call (returned in rax)
// and the object holding it (returned in rdx). // and the object holding it (returned in rdx).
__ push(context_register()); __ push(context_register());
__ Push(var->name()); __ Push(var->name());
__ CallRuntime(Runtime::kLoadContextSlot, 2); __ CallRuntime(Runtime::kLoadContextSlot, 2);
__ push(rax); // Function. __ push(rax); // Function.
__ push(rdx); // Receiver. __ push(rdx); // Receiver.
// If fast case code has been generated, emit code to push the // If fast case code has been generated, emit code to push the
// function and receiver and have the slow path jump around this // function and receiver and have the slow path jump around this
// code. // code.
if (done.is_linked()) { if (done.is_linked()) {
NearLabel call; NearLabel call;
__ jmp(&call); __ jmp(&call);
__ bind(&done); __ bind(&done);
// Push function. // Push function.
__ push(rax); __ push(rax);
// Push global receiver. // Push global receiver.
__ movq(rbx, CodeGenerator::GlobalObject()); __ movq(rbx, CodeGenerator::GlobalObject());
__ push(FieldOperand(rbx, GlobalObject::kGlobalReceiverOffset)); __ push(FieldOperand(rbx, GlobalObject::kGlobalReceiverOffset));
__ bind(&call); __ bind(&call);
}
} }
EmitCallWithStub(expr); EmitCallWithStub(expr);
@ -1873,18 +1883,24 @@ void FullCodeGenerator::VisitCall(Call* expr) {
Literal* key = prop->key()->AsLiteral(); Literal* key = prop->key()->AsLiteral();
if (key != NULL && key->handle()->IsSymbol()) { if (key != NULL && key->handle()->IsSymbol()) {
// Call to a named property, use call IC. // Call to a named property, use call IC.
VisitForStackValue(prop->obj()); { PreserveStatementPositionScope scope(masm()->positions_recorder());
VisitForStackValue(prop->obj());
}
EmitCallWithIC(expr, key->handle(), RelocInfo::CODE_TARGET); EmitCallWithIC(expr, key->handle(), RelocInfo::CODE_TARGET);
} else { } else {
// Call to a keyed property. // Call to a keyed property.
// For a synthetic property use keyed load IC followed by function call, // For a synthetic property use keyed load IC followed by function call,
// for a regular property use KeyedCallIC. // for a regular property use KeyedCallIC.
VisitForStackValue(prop->obj()); { PreserveStatementPositionScope scope(masm()->positions_recorder());
VisitForStackValue(prop->obj());
}
if (prop->is_synthetic()) { if (prop->is_synthetic()) {
VisitForAccumulatorValue(prop->key()); { PreserveStatementPositionScope scope(masm()->positions_recorder());
__ movq(rdx, Operand(rsp, 0)); VisitForAccumulatorValue(prop->key());
__ movq(rdx, Operand(rsp, 0));
}
// Record source code position for IC call. // Record source code position for IC call.
SetSourcePosition(prop->position()); SetSourcePosition(prop->position(), FORCED_POSITION);
Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize));
EmitCallIC(ic, RelocInfo::CODE_TARGET); EmitCallIC(ic, RelocInfo::CODE_TARGET);
// Pop receiver. // Pop receiver.
@ -1909,7 +1925,9 @@ void FullCodeGenerator::VisitCall(Call* expr) {
loop_depth() == 0) { loop_depth() == 0) {
lit->set_try_full_codegen(true); lit->set_try_full_codegen(true);
} }
VisitForStackValue(fun); { PreserveStatementPositionScope scope(masm()->positions_recorder());
VisitForStackValue(fun);
}
// Load global receiver object. // Load global receiver object.
__ movq(rbx, CodeGenerator::GlobalObject()); __ movq(rbx, CodeGenerator::GlobalObject());
__ push(FieldOperand(rbx, GlobalObject::kGlobalReceiverOffset)); __ push(FieldOperand(rbx, GlobalObject::kGlobalReceiverOffset));

View File

@ -0,0 +1,95 @@
// Copyright 2010 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following
// disclaimer in the documentation and/or other materials provided
// with the distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Flags: --always-full-compiler
var functionToCatch;
var lineNumber;
function catchLineNumber () {
var x = {};
Error.prepareStackTrace = function (error, stackTrace) {
stackTrace.some(function (frame) {
if (frame.getFunction() == functionToCatch) {
lineNumber = frame.getLineNumber();
return true;
}
return false;
});
return lineNumber;
};
Error.captureStackTrace(x);
return x.stack;
}
function log() {
catchLineNumber();
}
function foo() {}
function test1() {
log(foo() == foo()
? 'a'
: 'b');
}
function test2() {
var o = { foo: function () {}}
log(o.foo() == o.foo()
? 'a'
: 'b');
}
function test3() {
var o = { log: log, foo: function() { } };
o.log(o.foo() == o.foo()
? 'a'
: 'b');
}
function test(f, expectedLineNumber) {
functionToCatch = f;
f();
assertEquals(expectedLineNumber, lineNumber);
}
test(test1, 58);
test(test2, 65);
test(test3, 72);
eval(test1.toString() + "//@ sourceUrl=foo");
eval(test2.toString() + "//@ sourceUrl=foo");
eval(test3.toString() + "//@ sourceUrl=foo");
test(test1, 2);
test(test2, 3);
test(test3, 3);