Debugger: use debug break slots instead of ICs (except for calls).
BUG=v8:3147,v8:4269 LOG=N Review URL: https://codereview.chromium.org/1218493005 Cr-Commit-Position: refs/heads/master@{#29487}
This commit is contained in:
parent
ef661b0804
commit
a8a4c364c2
@ -140,50 +140,6 @@ void DebugCodegen::GenerateCallICStubDebugBreak(MacroAssembler* masm) {
|
||||
}
|
||||
|
||||
|
||||
void DebugCodegen::GenerateLoadICDebugBreak(MacroAssembler* masm) {
|
||||
// Calling convention for IC load (from ic-arm.cc).
|
||||
Register receiver = LoadDescriptor::ReceiverRegister();
|
||||
Register name = LoadDescriptor::NameRegister();
|
||||
Register slot = LoadDescriptor::SlotRegister();
|
||||
RegList regs = receiver.bit() | name.bit() | slot.bit();
|
||||
Generate_DebugBreakCallHelper(masm, regs, 0);
|
||||
}
|
||||
|
||||
|
||||
void DebugCodegen::GenerateStoreICDebugBreak(MacroAssembler* masm) {
|
||||
// Calling convention for IC store (from ic-arm.cc).
|
||||
Register receiver = StoreDescriptor::ReceiverRegister();
|
||||
Register name = StoreDescriptor::NameRegister();
|
||||
Register value = StoreDescriptor::ValueRegister();
|
||||
RegList regs = receiver.bit() | name.bit() | value.bit();
|
||||
if (FLAG_vector_stores) {
|
||||
regs |= VectorStoreICDescriptor::SlotRegister().bit();
|
||||
}
|
||||
Generate_DebugBreakCallHelper(masm, regs, 0);
|
||||
}
|
||||
|
||||
|
||||
void DebugCodegen::GenerateKeyedLoadICDebugBreak(MacroAssembler* masm) {
|
||||
// Calling convention for keyed IC load (from ic-arm.cc).
|
||||
GenerateLoadICDebugBreak(masm);
|
||||
}
|
||||
|
||||
|
||||
void DebugCodegen::GenerateKeyedStoreICDebugBreak(MacroAssembler* masm) {
|
||||
// Calling convention for IC keyed store call (from ic-arm.cc).
|
||||
GenerateStoreICDebugBreak(masm);
|
||||
}
|
||||
|
||||
|
||||
void DebugCodegen::GenerateCompareNilICDebugBreak(MacroAssembler* masm) {
|
||||
// Register state for CompareNil IC
|
||||
// ----------- S t a t e -------------
|
||||
// -- r0 : value
|
||||
// -----------------------------------
|
||||
Generate_DebugBreakCallHelper(masm, r0.bit(), 0);
|
||||
}
|
||||
|
||||
|
||||
void DebugCodegen::GenerateReturnDebugBreak(MacroAssembler* masm) {
|
||||
// In places other than IC call sites it is expected that r0 is TOS which
|
||||
// is an object - this is not generally the case so this should be used with
|
||||
|
@ -508,7 +508,7 @@ void FullCodeGenerator::EmitReturnSequence() {
|
||||
{ Assembler::BlockConstPoolScope block_const_pool(masm_);
|
||||
int32_t arg_count = info_->scope()->num_parameters() + 1;
|
||||
int32_t sp_delta = arg_count * kPointerSize;
|
||||
CodeGenerator::RecordPositions(masm_, function()->end_position() - 1);
|
||||
SetReturnPosition(function());
|
||||
// TODO(svenpanne) The code below is sometimes 4 words, sometimes 5!
|
||||
PredictableCodeSizeScope predictable(masm_, -1);
|
||||
__ RecordJSReturn();
|
||||
@ -1080,7 +1080,7 @@ void FullCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) {
|
||||
}
|
||||
|
||||
// Record position before stub call for type feedback.
|
||||
SetSourcePosition(clause->position());
|
||||
SetExpressionPosition(clause);
|
||||
Handle<Code> ic = CodeFactory::CompareIC(isolate(), Token::EQ_STRICT,
|
||||
strength(language_mode())).code();
|
||||
CallIC(ic, clause->CompareId());
|
||||
@ -1128,8 +1128,9 @@ void FullCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) {
|
||||
|
||||
void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
|
||||
Comment cmnt(masm_, "[ ForInStatement");
|
||||
SetStatementPosition(stmt, SKIP_BREAK);
|
||||
|
||||
FeedbackVectorSlot slot = stmt->ForInFeedbackSlot();
|
||||
SetStatementPosition(stmt);
|
||||
|
||||
Label loop, exit;
|
||||
ForIn loop_statement(this, stmt);
|
||||
@ -1137,7 +1138,7 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
|
||||
|
||||
// Get the object to enumerate over. If the object is null or undefined, skip
|
||||
// over the loop. See ECMA-262 version 5, section 12.6.4.
|
||||
SetExpressionPosition(stmt->enumerable());
|
||||
SetExpressionAsStatementPosition(stmt->enumerable());
|
||||
VisitForAccumulatorValue(stmt->enumerable());
|
||||
__ LoadRoot(ip, Heap::kUndefinedValueRootIndex);
|
||||
__ cmp(r0, ip);
|
||||
@ -1241,7 +1242,7 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
|
||||
// Generate code for doing the condition check.
|
||||
PrepareForBailoutForId(stmt->BodyId(), NO_REGISTERS);
|
||||
__ bind(&loop);
|
||||
SetExpressionPosition(stmt->each());
|
||||
SetExpressionAsStatementPosition(stmt->each());
|
||||
|
||||
// Load the current count to r0, load the length to r1.
|
||||
__ Ldrd(r0, r1, MemOperand(sp, 0 * kPointerSize));
|
||||
@ -1491,7 +1492,7 @@ void FullCodeGenerator::EmitDynamicLookupFastCase(VariableProxy* proxy,
|
||||
|
||||
void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy) {
|
||||
// Record position before possible IC call.
|
||||
SetSourcePosition(proxy->position());
|
||||
SetExpressionPosition(proxy);
|
||||
PrepareForBailoutForId(proxy->BeforeId(), NO_REGISTERS);
|
||||
Variable* var = proxy->var();
|
||||
|
||||
@ -1986,6 +1987,7 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) {
|
||||
DCHECK(expr->target()->IsValidReferenceExpression());
|
||||
|
||||
Comment cmnt(masm_, "[ Assignment");
|
||||
SetExpressionPosition(expr, INSERT_BREAK);
|
||||
|
||||
Property* property = expr->target()->AsProperty();
|
||||
LhsKind assign_type = Property::GetAssignType(property);
|
||||
@ -2079,7 +2081,6 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) {
|
||||
__ push(r0); // Left operand goes on the stack.
|
||||
VisitForAccumulatorValue(expr->value());
|
||||
|
||||
SetSourcePosition(expr->position() + 1);
|
||||
AccumulatorValueContext context(this);
|
||||
if (ShouldInlineSmiCase(op)) {
|
||||
EmitInlineSmiBinaryOp(expr->binary_operation(),
|
||||
@ -2096,8 +2097,7 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) {
|
||||
VisitForAccumulatorValue(expr->value());
|
||||
}
|
||||
|
||||
// Record source position before possible IC call.
|
||||
SetSourcePosition(expr->position());
|
||||
SetExpressionPosition(expr);
|
||||
|
||||
// Store the value.
|
||||
switch (assign_type) {
|
||||
@ -2127,6 +2127,8 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) {
|
||||
|
||||
void FullCodeGenerator::VisitYield(Yield* expr) {
|
||||
Comment cmnt(masm_, "[ Yield");
|
||||
SetExpressionPosition(expr);
|
||||
|
||||
// Evaluate yielded value first; the initial iterator definition depends on
|
||||
// this. It stays on the stack while we update the iterator.
|
||||
VisitForStackValue(expr->expression());
|
||||
@ -2422,7 +2424,7 @@ void FullCodeGenerator::EmitCreateIteratorResult(bool done) {
|
||||
|
||||
|
||||
void FullCodeGenerator::EmitNamedPropertyLoad(Property* prop) {
|
||||
SetSourcePosition(prop->position());
|
||||
SetExpressionPosition(prop);
|
||||
Literal* key = prop->key()->AsLiteral();
|
||||
DCHECK(!prop->IsSuperAccess());
|
||||
|
||||
@ -2435,7 +2437,7 @@ void FullCodeGenerator::EmitNamedPropertyLoad(Property* prop) {
|
||||
|
||||
void FullCodeGenerator::EmitNamedSuperPropertyLoad(Property* prop) {
|
||||
// Stack: receiver, home_object.
|
||||
SetSourcePosition(prop->position());
|
||||
SetExpressionPosition(prop);
|
||||
Literal* key = prop->key()->AsLiteral();
|
||||
DCHECK(!key->value()->IsSmi());
|
||||
DCHECK(prop->IsSuperAccess());
|
||||
@ -2447,7 +2449,7 @@ void FullCodeGenerator::EmitNamedSuperPropertyLoad(Property* prop) {
|
||||
|
||||
|
||||
void FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) {
|
||||
SetSourcePosition(prop->position());
|
||||
SetExpressionPosition(prop);
|
||||
Handle<Code> ic = CodeFactory::KeyedLoadIC(isolate(), language_mode()).code();
|
||||
__ mov(LoadDescriptor::SlotRegister(),
|
||||
Operand(SmiFromSlot(prop->PropertyFeedbackSlot())));
|
||||
@ -2457,9 +2459,8 @@ void FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) {
|
||||
|
||||
void FullCodeGenerator::EmitKeyedSuperPropertyLoad(Property* prop) {
|
||||
// Stack: receiver, home_object, key.
|
||||
SetExpressionPosition(prop);
|
||||
__ Push(Smi::FromInt(language_mode()));
|
||||
SetSourcePosition(prop->position());
|
||||
|
||||
__ CallRuntime(Runtime::kLoadKeyedFromSuper, 4);
|
||||
}
|
||||
|
||||
@ -2832,8 +2833,6 @@ void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) {
|
||||
DCHECK(prop != NULL);
|
||||
DCHECK(prop->key()->IsLiteral());
|
||||
|
||||
// Record source code position before IC call.
|
||||
SetSourcePosition(expr->position());
|
||||
__ mov(StoreDescriptor::NameRegister(),
|
||||
Operand(prop->key()->AsLiteral()->value()));
|
||||
__ pop(StoreDescriptor::ReceiverRegister());
|
||||
@ -2881,9 +2880,6 @@ void FullCodeGenerator::EmitKeyedSuperPropertyStore(Property* prop) {
|
||||
|
||||
void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) {
|
||||
// Assignment to a property, using a keyed store IC.
|
||||
|
||||
// Record source code position before IC call.
|
||||
SetSourcePosition(expr->position());
|
||||
__ Pop(StoreDescriptor::ReceiverRegister(), StoreDescriptor::NameRegister());
|
||||
DCHECK(StoreDescriptor::ValueRegister().is(r0));
|
||||
|
||||
@ -2903,6 +2899,8 @@ void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) {
|
||||
|
||||
void FullCodeGenerator::VisitProperty(Property* expr) {
|
||||
Comment cmnt(masm_, "[ Property");
|
||||
SetExpressionPosition(expr);
|
||||
|
||||
Expression* key = expr->key();
|
||||
|
||||
if (key->IsPropertyName()) {
|
||||
@ -2985,8 +2983,8 @@ void FullCodeGenerator::EmitSuperCallWithLoadIC(Call* expr) {
|
||||
DCHECK(callee->IsProperty());
|
||||
Property* prop = callee->AsProperty();
|
||||
DCHECK(prop->IsSuperAccess());
|
||||
SetExpressionPosition(prop);
|
||||
|
||||
SetSourcePosition(prop->position());
|
||||
Literal* key = prop->key()->AsLiteral();
|
||||
DCHECK(!key->value()->IsSmi());
|
||||
// Load the function from the receiver.
|
||||
@ -3050,7 +3048,7 @@ void FullCodeGenerator::EmitKeyedSuperCallWithLoadIC(Call* expr) {
|
||||
Property* prop = callee->AsProperty();
|
||||
DCHECK(prop->IsSuperAccess());
|
||||
|
||||
SetSourcePosition(prop->position());
|
||||
SetExpressionPosition(prop);
|
||||
// Load the function from the receiver.
|
||||
const Register scratch = r1;
|
||||
SuperPropertyReference* super_ref = prop->obj()->AsSuperPropertyReference();
|
||||
@ -3086,14 +3084,11 @@ void FullCodeGenerator::EmitCall(Call* expr, CallICState::CallType call_type) {
|
||||
// Load the arguments.
|
||||
ZoneList<Expression*>* args = expr->arguments();
|
||||
int arg_count = args->length();
|
||||
{ PreservePositionScope scope(masm()->positions_recorder());
|
||||
for (int i = 0; i < arg_count; i++) {
|
||||
VisitForStackValue(args->at(i));
|
||||
}
|
||||
for (int i = 0; i < arg_count; i++) {
|
||||
VisitForStackValue(args->at(i));
|
||||
}
|
||||
|
||||
// Record source position of the IC call.
|
||||
SetSourcePosition(expr->position());
|
||||
SetExpressionPosition(expr);
|
||||
Handle<Code> ic = CodeFactory::CallIC(isolate(), arg_count, call_type).code();
|
||||
__ mov(r3, Operand(SmiFromSlot(expr->CallFeedbackICSlot())));
|
||||
__ ldr(r1, MemOperand(sp, (arg_count + 1) * kPointerSize));
|
||||
@ -3152,13 +3147,10 @@ void FullCodeGenerator::PushCalleeAndWithBaseObject(Call* expr) {
|
||||
VariableProxy* callee = expr->expression()->AsVariableProxy();
|
||||
if (callee->var()->IsLookupSlot()) {
|
||||
Label slow, done;
|
||||
SetSourcePosition(callee->position());
|
||||
{
|
||||
PreservePositionScope scope(masm()->positions_recorder());
|
||||
// Generate code for loading from variables potentially shadowed
|
||||
// by eval-introduced variables.
|
||||
EmitDynamicLookupFastCase(callee, NOT_INSIDE_TYPEOF, &slow, &done);
|
||||
}
|
||||
SetExpressionPosition(callee);
|
||||
// Generate code for loading from variables potentially shadowed
|
||||
// by eval-introduced variables.
|
||||
EmitDynamicLookupFastCase(callee, NOT_INSIDE_TYPEOF, &slow, &done);
|
||||
|
||||
__ bind(&slow);
|
||||
// Call the runtime to find the function to call (returned in r0)
|
||||
@ -3212,28 +3204,26 @@ void FullCodeGenerator::VisitCall(Call* expr) {
|
||||
ZoneList<Expression*>* args = expr->arguments();
|
||||
int arg_count = args->length();
|
||||
|
||||
{ PreservePositionScope pos_scope(masm()->positions_recorder());
|
||||
PushCalleeAndWithBaseObject(expr);
|
||||
PushCalleeAndWithBaseObject(expr);
|
||||
|
||||
// Push the arguments.
|
||||
for (int i = 0; i < arg_count; i++) {
|
||||
VisitForStackValue(args->at(i));
|
||||
}
|
||||
|
||||
// Push a copy of the function (found below the arguments) and
|
||||
// resolve eval.
|
||||
__ ldr(r1, MemOperand(sp, (arg_count + 1) * kPointerSize));
|
||||
__ push(r1);
|
||||
EmitResolvePossiblyDirectEval(arg_count);
|
||||
|
||||
// Touch up the stack with the resolved function.
|
||||
__ str(r0, MemOperand(sp, (arg_count + 1) * kPointerSize));
|
||||
|
||||
PrepareForBailoutForId(expr->EvalId(), NO_REGISTERS);
|
||||
// Push the arguments.
|
||||
for (int i = 0; i < arg_count; i++) {
|
||||
VisitForStackValue(args->at(i));
|
||||
}
|
||||
|
||||
// Push a copy of the function (found below the arguments) and
|
||||
// resolve eval.
|
||||
__ ldr(r1, MemOperand(sp, (arg_count + 1) * kPointerSize));
|
||||
__ push(r1);
|
||||
EmitResolvePossiblyDirectEval(arg_count);
|
||||
|
||||
// Touch up the stack with the resolved function.
|
||||
__ str(r0, MemOperand(sp, (arg_count + 1) * kPointerSize));
|
||||
|
||||
PrepareForBailoutForId(expr->EvalId(), NO_REGISTERS);
|
||||
|
||||
// Record source position for debugger.
|
||||
SetSourcePosition(expr->position());
|
||||
SetExpressionPosition(expr);
|
||||
CallFunctionStub stub(isolate(), arg_count, NO_CALL_FUNCTION_FLAGS);
|
||||
__ ldr(r1, MemOperand(sp, (arg_count + 1) * kPointerSize));
|
||||
__ CallStub(&stub);
|
||||
@ -3258,10 +3248,7 @@ void FullCodeGenerator::VisitCall(Call* expr) {
|
||||
EmitKeyedSuperCallWithLoadIC(expr);
|
||||
}
|
||||
} else {
|
||||
{
|
||||
PreservePositionScope scope(masm()->positions_recorder());
|
||||
VisitForStackValue(property->obj());
|
||||
}
|
||||
if (is_named_call) {
|
||||
EmitCallWithLoadIC(expr);
|
||||
} else {
|
||||
@ -3273,9 +3260,7 @@ void FullCodeGenerator::VisitCall(Call* expr) {
|
||||
} else {
|
||||
DCHECK(call_type == Call::OTHER_CALL);
|
||||
// Call to an arbitrary expression not handled specially above.
|
||||
{ PreservePositionScope scope(masm()->positions_recorder());
|
||||
VisitForStackValue(callee);
|
||||
}
|
||||
VisitForStackValue(callee);
|
||||
__ LoadRoot(r1, Heap::kUndefinedValueRootIndex);
|
||||
__ push(r1);
|
||||
// Emit function call.
|
||||
@ -3310,7 +3295,7 @@ void FullCodeGenerator::VisitCallNew(CallNew* expr) {
|
||||
|
||||
// Call the construct call builtin that handles allocation and
|
||||
// constructor invocation.
|
||||
SetSourcePosition(expr->position());
|
||||
SetExpressionPosition(expr);
|
||||
|
||||
// Load function and argument count into r1 and r0.
|
||||
__ mov(r0, Operand(arg_count));
|
||||
@ -3353,7 +3338,7 @@ void FullCodeGenerator::EmitSuperConstructorCall(Call* expr) {
|
||||
|
||||
// Call the construct call builtin that handles allocation and
|
||||
// constructor invocation.
|
||||
SetSourcePosition(expr->position());
|
||||
SetExpressionPosition(expr);
|
||||
|
||||
// Load function and argument count into r1 and r0.
|
||||
__ mov(r0, Operand(arg_count));
|
||||
@ -4732,8 +4717,7 @@ void FullCodeGenerator::EmitCallJSRuntimeFunction(CallRuntime* expr) {
|
||||
ZoneList<Expression*>* args = expr->arguments();
|
||||
int arg_count = args->length();
|
||||
|
||||
// Record source position of the IC call.
|
||||
SetSourcePosition(expr->position());
|
||||
SetExpressionPosition(expr);
|
||||
CallFunctionStub stub(isolate(), arg_count, NO_CALL_FUNCTION_FLAGS);
|
||||
__ ldr(r1, MemOperand(sp, (arg_count + 1) * kPointerSize));
|
||||
__ CallStub(&stub);
|
||||
@ -4911,7 +4895,6 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
|
||||
DCHECK(expr->expression()->IsValidReferenceExpression());
|
||||
|
||||
Comment cmnt(masm_, "[ CountOperation");
|
||||
SetSourcePosition(expr->position());
|
||||
|
||||
Property* prop = expr->expression()->AsProperty();
|
||||
LhsKind assign_type = Property::GetAssignType(prop);
|
||||
@ -5067,8 +5050,7 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
|
||||
__ mov(r1, r0);
|
||||
__ mov(r0, Operand(Smi::FromInt(count_value)));
|
||||
|
||||
// Record position before stub call.
|
||||
SetSourcePosition(expr->position());
|
||||
SetExpressionPosition(expr);
|
||||
|
||||
Handle<Code> code = CodeFactory::BinaryOpIC(isolate(), Token::ADD,
|
||||
strength(language_mode())).code();
|
||||
@ -5284,7 +5266,7 @@ void FullCodeGenerator::EmitLiteralCompareTypeof(Expression* expr,
|
||||
|
||||
void FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) {
|
||||
Comment cmnt(masm_, "[ CompareOperation");
|
||||
SetSourcePosition(expr->position());
|
||||
SetExpressionPosition(expr);
|
||||
|
||||
// First we try a fast inlined version of the compare when one of
|
||||
// the operands is a literal.
|
||||
@ -5338,8 +5320,6 @@ void FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) {
|
||||
__ bind(&slow_case);
|
||||
}
|
||||
|
||||
// Record position and call the compare IC.
|
||||
SetSourcePosition(expr->position());
|
||||
Handle<Code> ic = CodeFactory::CompareIC(
|
||||
isolate(), op, strength(language_mode())).code();
|
||||
CallIC(ic, expr->CompareOperationFeedbackId());
|
||||
|
@ -203,50 +203,6 @@ void DebugCodegen::GenerateCallICStubDebugBreak(MacroAssembler* masm) {
|
||||
}
|
||||
|
||||
|
||||
void DebugCodegen::GenerateLoadICDebugBreak(MacroAssembler* masm) {
|
||||
// Calling convention for IC load (from ic-arm.cc).
|
||||
Register receiver = LoadDescriptor::ReceiverRegister();
|
||||
Register name = LoadDescriptor::NameRegister();
|
||||
Register slot = LoadDescriptor::SlotRegister();
|
||||
RegList regs = receiver.Bit() | name.Bit() | slot.Bit();
|
||||
Generate_DebugBreakCallHelper(masm, regs, 0, x10);
|
||||
}
|
||||
|
||||
|
||||
void DebugCodegen::GenerateStoreICDebugBreak(MacroAssembler* masm) {
|
||||
// Calling convention for IC store (from ic-arm64.cc).
|
||||
Register receiver = StoreDescriptor::ReceiverRegister();
|
||||
Register name = StoreDescriptor::NameRegister();
|
||||
Register value = StoreDescriptor::ValueRegister();
|
||||
RegList regs = receiver.Bit() | name.Bit() | value.Bit();
|
||||
if (FLAG_vector_stores) {
|
||||
regs |= VectorStoreICDescriptor::SlotRegister().Bit();
|
||||
}
|
||||
Generate_DebugBreakCallHelper(masm, regs, 0, x10);
|
||||
}
|
||||
|
||||
|
||||
void DebugCodegen::GenerateKeyedLoadICDebugBreak(MacroAssembler* masm) {
|
||||
// Calling convention for keyed IC load (from ic-arm.cc).
|
||||
GenerateLoadICDebugBreak(masm);
|
||||
}
|
||||
|
||||
|
||||
void DebugCodegen::GenerateKeyedStoreICDebugBreak(MacroAssembler* masm) {
|
||||
// Calling convention for IC keyed store call (from ic-arm64.cc).
|
||||
GenerateStoreICDebugBreak(masm);
|
||||
}
|
||||
|
||||
|
||||
void DebugCodegen::GenerateCompareNilICDebugBreak(MacroAssembler* masm) {
|
||||
// Register state for CompareNil IC
|
||||
// ----------- S t a t e -------------
|
||||
// -- r0 : value
|
||||
// -----------------------------------
|
||||
Generate_DebugBreakCallHelper(masm, x0.Bit(), 0, x10);
|
||||
}
|
||||
|
||||
|
||||
void DebugCodegen::GenerateReturnDebugBreak(MacroAssembler* masm) {
|
||||
// In places other than IC call sites it is expected that r0 is TOS which
|
||||
// is an object - this is not generally the case so this should be used with
|
||||
|
@ -498,7 +498,7 @@ void FullCodeGenerator::EmitReturnSequence() {
|
||||
{
|
||||
InstructionAccurateScope scope(masm_,
|
||||
Assembler::kJSReturnSequenceInstructions);
|
||||
CodeGenerator::RecordPositions(masm_, function()->end_position() - 1);
|
||||
SetReturnPosition(function());
|
||||
__ RecordJSReturn();
|
||||
// This code is generated using Assembler methods rather than Macro
|
||||
// Assembler methods because it will be patched later on, and so the size
|
||||
@ -1080,7 +1080,7 @@ void FullCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) {
|
||||
}
|
||||
|
||||
// Record position before stub call for type feedback.
|
||||
SetSourcePosition(clause->position());
|
||||
SetExpressionPosition(clause);
|
||||
Handle<Code> ic = CodeFactory::CompareIC(isolate(), Token::EQ_STRICT,
|
||||
strength(language_mode())).code();
|
||||
CallIC(ic, clause->CompareId());
|
||||
@ -1126,9 +1126,11 @@ void FullCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) {
|
||||
void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
|
||||
ASM_LOCATION("FullCodeGenerator::VisitForInStatement");
|
||||
Comment cmnt(masm_, "[ ForInStatement");
|
||||
SetStatementPosition(stmt, SKIP_BREAK);
|
||||
|
||||
FeedbackVectorSlot slot = stmt->ForInFeedbackSlot();
|
||||
|
||||
// TODO(all): This visitor probably needs better comments and a revisit.
|
||||
SetStatementPosition(stmt);
|
||||
|
||||
Label loop, exit;
|
||||
ForIn loop_statement(this, stmt);
|
||||
@ -1136,7 +1138,7 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
|
||||
|
||||
// Get the object to enumerate over. If the object is null or undefined, skip
|
||||
// over the loop. See ECMA-262 version 5, section 12.6.4.
|
||||
SetExpressionPosition(stmt->enumerable());
|
||||
SetExpressionAsStatementPosition(stmt->enumerable());
|
||||
VisitForAccumulatorValue(stmt->enumerable());
|
||||
__ JumpIfRoot(x0, Heap::kUndefinedValueRootIndex, &exit);
|
||||
Register null_value = x15;
|
||||
@ -1230,7 +1232,7 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
|
||||
// Generate code for doing the condition check.
|
||||
PrepareForBailoutForId(stmt->BodyId(), NO_REGISTERS);
|
||||
__ Bind(&loop);
|
||||
SetExpressionPosition(stmt->each());
|
||||
SetExpressionAsStatementPosition(stmt->each());
|
||||
|
||||
// Load the current count to x0, load the length to x1.
|
||||
__ PeekPair(x0, x1, 0);
|
||||
@ -1469,7 +1471,7 @@ void FullCodeGenerator::EmitDynamicLookupFastCase(VariableProxy* proxy,
|
||||
|
||||
void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy) {
|
||||
// Record position before possible IC call.
|
||||
SetSourcePosition(proxy->position());
|
||||
SetExpressionPosition(proxy);
|
||||
PrepareForBailoutForId(proxy->BeforeId(), NO_REGISTERS);
|
||||
Variable* var = proxy->var();
|
||||
|
||||
@ -1959,6 +1961,7 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) {
|
||||
DCHECK(expr->target()->IsValidReferenceExpression());
|
||||
|
||||
Comment cmnt(masm_, "[ Assignment");
|
||||
SetExpressionPosition(expr, INSERT_BREAK);
|
||||
|
||||
Property* property = expr->target()->AsProperty();
|
||||
LhsKind assign_type = Property::GetAssignType(property);
|
||||
@ -2049,7 +2052,6 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) {
|
||||
__ Push(x0); // Left operand goes on the stack.
|
||||
VisitForAccumulatorValue(expr->value());
|
||||
|
||||
SetSourcePosition(expr->position() + 1);
|
||||
AccumulatorValueContext context(this);
|
||||
if (ShouldInlineSmiCase(op)) {
|
||||
EmitInlineSmiBinaryOp(expr->binary_operation(),
|
||||
@ -2066,8 +2068,7 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) {
|
||||
VisitForAccumulatorValue(expr->value());
|
||||
}
|
||||
|
||||
// Record source position before possible IC call.
|
||||
SetSourcePosition(expr->position());
|
||||
SetExpressionPosition(expr);
|
||||
|
||||
// Store the value.
|
||||
switch (assign_type) {
|
||||
@ -2096,7 +2097,7 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) {
|
||||
|
||||
|
||||
void FullCodeGenerator::EmitNamedPropertyLoad(Property* prop) {
|
||||
SetSourcePosition(prop->position());
|
||||
SetExpressionPosition(prop);
|
||||
Literal* key = prop->key()->AsLiteral();
|
||||
DCHECK(!prop->IsSuperAccess());
|
||||
|
||||
@ -2109,7 +2110,7 @@ void FullCodeGenerator::EmitNamedPropertyLoad(Property* prop) {
|
||||
|
||||
void FullCodeGenerator::EmitNamedSuperPropertyLoad(Property* prop) {
|
||||
// Stack: receiver, home_object.
|
||||
SetSourcePosition(prop->position());
|
||||
SetExpressionPosition(prop);
|
||||
Literal* key = prop->key()->AsLiteral();
|
||||
DCHECK(!key->value()->IsSmi());
|
||||
DCHECK(prop->IsSuperAccess());
|
||||
@ -2121,7 +2122,7 @@ void FullCodeGenerator::EmitNamedSuperPropertyLoad(Property* prop) {
|
||||
|
||||
|
||||
void FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) {
|
||||
SetSourcePosition(prop->position());
|
||||
SetExpressionPosition(prop);
|
||||
// Call keyed load IC. It has arguments key and receiver in x0 and x1.
|
||||
Handle<Code> ic = CodeFactory::KeyedLoadIC(isolate(), language_mode()).code();
|
||||
__ Mov(LoadDescriptor::SlotRegister(),
|
||||
@ -2132,9 +2133,8 @@ void FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) {
|
||||
|
||||
void FullCodeGenerator::EmitKeyedSuperPropertyLoad(Property* prop) {
|
||||
// Stack: receiver, home_object, key.
|
||||
SetExpressionPosition(prop);
|
||||
__ Push(Smi::FromInt(language_mode()));
|
||||
SetSourcePosition(prop->position());
|
||||
|
||||
__ CallRuntime(Runtime::kLoadKeyedFromSuper, 4);
|
||||
}
|
||||
|
||||
@ -2518,8 +2518,6 @@ void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) {
|
||||
DCHECK(prop != NULL);
|
||||
DCHECK(prop->key()->IsLiteral());
|
||||
|
||||
// Record source code position before IC call.
|
||||
SetSourcePosition(expr->position());
|
||||
__ Mov(StoreDescriptor::NameRegister(),
|
||||
Operand(prop->key()->AsLiteral()->value()));
|
||||
__ Pop(StoreDescriptor::ReceiverRegister());
|
||||
@ -2569,8 +2567,6 @@ void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) {
|
||||
ASM_LOCATION("FullCodeGenerator::EmitKeyedPropertyAssignment");
|
||||
// Assignment to a property, using a keyed store IC.
|
||||
|
||||
// Record source code position before IC call.
|
||||
SetSourcePosition(expr->position());
|
||||
// TODO(all): Could we pass this in registers rather than on the stack?
|
||||
__ Pop(StoreDescriptor::NameRegister(), StoreDescriptor::ReceiverRegister());
|
||||
DCHECK(StoreDescriptor::ValueRegister().is(x0));
|
||||
@ -2591,6 +2587,7 @@ void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) {
|
||||
|
||||
void FullCodeGenerator::VisitProperty(Property* expr) {
|
||||
Comment cmnt(masm_, "[ Property");
|
||||
SetExpressionPosition(expr);
|
||||
Expression* key = expr->key();
|
||||
|
||||
if (key->IsPropertyName()) {
|
||||
@ -2675,8 +2672,8 @@ void FullCodeGenerator::EmitSuperCallWithLoadIC(Call* expr) {
|
||||
DCHECK(callee->IsProperty());
|
||||
Property* prop = callee->AsProperty();
|
||||
DCHECK(prop->IsSuperAccess());
|
||||
SetExpressionPosition(prop);
|
||||
|
||||
SetSourcePosition(prop->position());
|
||||
Literal* key = prop->key()->AsLiteral();
|
||||
DCHECK(!key->value()->IsSmi());
|
||||
|
||||
@ -2738,8 +2735,7 @@ void FullCodeGenerator::EmitKeyedSuperCallWithLoadIC(Call* expr) {
|
||||
DCHECK(callee->IsProperty());
|
||||
Property* prop = callee->AsProperty();
|
||||
DCHECK(prop->IsSuperAccess());
|
||||
|
||||
SetSourcePosition(prop->position());
|
||||
SetExpressionPosition(prop);
|
||||
|
||||
// Load the function from the receiver.
|
||||
const Register scratch = x10;
|
||||
@ -2776,13 +2772,10 @@ void FullCodeGenerator::EmitCall(Call* expr, CallICState::CallType call_type) {
|
||||
// Load the arguments.
|
||||
ZoneList<Expression*>* args = expr->arguments();
|
||||
int arg_count = args->length();
|
||||
{ PreservePositionScope scope(masm()->positions_recorder());
|
||||
for (int i = 0; i < arg_count; i++) {
|
||||
VisitForStackValue(args->at(i));
|
||||
}
|
||||
}
|
||||
// Record source position of the IC call.
|
||||
SetSourcePosition(expr->position());
|
||||
SetExpressionPosition(expr);
|
||||
|
||||
Handle<Code> ic = CodeFactory::CallIC(isolate(), arg_count, call_type).code();
|
||||
__ Mov(x3, SmiFromSlot(expr->CallFeedbackICSlot()));
|
||||
@ -2843,13 +2836,10 @@ void FullCodeGenerator::PushCalleeAndWithBaseObject(Call* expr) {
|
||||
VariableProxy* callee = expr->expression()->AsVariableProxy();
|
||||
if (callee->var()->IsLookupSlot()) {
|
||||
Label slow, done;
|
||||
SetSourcePosition(callee->position());
|
||||
{
|
||||
PreservePositionScope scope(masm()->positions_recorder());
|
||||
SetExpressionPosition(callee);
|
||||
// Generate code for loading from variables potentially shadowed
|
||||
// by eval-introduced variables.
|
||||
EmitDynamicLookupFastCase(callee, NOT_INSIDE_TYPEOF, &slow, &done);
|
||||
}
|
||||
|
||||
__ Bind(&slow);
|
||||
// Call the runtime to find the function to call (returned in x0)
|
||||
@ -2901,8 +2891,6 @@ void FullCodeGenerator::VisitCall(Call* expr) {
|
||||
ZoneList<Expression*>* args = expr->arguments();
|
||||
int arg_count = args->length();
|
||||
|
||||
{
|
||||
PreservePositionScope pos_scope(masm()->positions_recorder());
|
||||
PushCalleeAndWithBaseObject(expr);
|
||||
|
||||
// Push the arguments.
|
||||
@ -2920,10 +2908,9 @@ void FullCodeGenerator::VisitCall(Call* expr) {
|
||||
__ Poke(x0, (arg_count + 1) * kPointerSize);
|
||||
|
||||
PrepareForBailoutForId(expr->EvalId(), NO_REGISTERS);
|
||||
}
|
||||
|
||||
// Record source position for debugger.
|
||||
SetSourcePosition(expr->position());
|
||||
SetExpressionPosition(expr);
|
||||
|
||||
// Call the evaluated function.
|
||||
CallFunctionStub stub(isolate(), arg_count, NO_CALL_FUNCTION_FLAGS);
|
||||
@ -2951,10 +2938,7 @@ void FullCodeGenerator::VisitCall(Call* expr) {
|
||||
EmitKeyedSuperCallWithLoadIC(expr);
|
||||
}
|
||||
} else {
|
||||
{
|
||||
PreservePositionScope scope(masm()->positions_recorder());
|
||||
VisitForStackValue(property->obj());
|
||||
}
|
||||
if (is_named_call) {
|
||||
EmitCallWithLoadIC(expr);
|
||||
} else {
|
||||
@ -2966,9 +2950,7 @@ void FullCodeGenerator::VisitCall(Call* expr) {
|
||||
} else {
|
||||
DCHECK(call_type == Call::OTHER_CALL);
|
||||
// Call to an arbitrary expression not handled specially above.
|
||||
{ PreservePositionScope scope(masm()->positions_recorder());
|
||||
VisitForStackValue(callee);
|
||||
}
|
||||
__ LoadRoot(x1, Heap::kUndefinedValueRootIndex);
|
||||
__ Push(x1);
|
||||
// Emit function call.
|
||||
@ -3003,7 +2985,7 @@ void FullCodeGenerator::VisitCallNew(CallNew* expr) {
|
||||
|
||||
// Call the construct call builtin that handles allocation and
|
||||
// constructor invocation.
|
||||
SetSourcePosition(expr->position());
|
||||
SetExpressionPosition(expr);
|
||||
|
||||
// Load function and argument count into x1 and x0.
|
||||
__ Mov(x0, arg_count);
|
||||
@ -3046,7 +3028,7 @@ void FullCodeGenerator::EmitSuperConstructorCall(Call* expr) {
|
||||
|
||||
// Call the construct call builtin that handles allocation and
|
||||
// constructor invocation.
|
||||
SetSourcePosition(expr->position());
|
||||
SetExpressionPosition(expr);
|
||||
|
||||
// Load function and argument count into x1 and x0.
|
||||
__ Mov(x0, arg_count);
|
||||
@ -4426,8 +4408,7 @@ void FullCodeGenerator::EmitCallJSRuntimeFunction(CallRuntime* expr) {
|
||||
ZoneList<Expression*>* args = expr->arguments();
|
||||
int arg_count = args->length();
|
||||
|
||||
// Record source position of the IC call.
|
||||
SetSourcePosition(expr->position());
|
||||
SetExpressionPosition(expr);
|
||||
CallFunctionStub stub(isolate(), arg_count, NO_CALL_FUNCTION_FLAGS);
|
||||
__ Peek(x1, (arg_count + 1) * kPointerSize);
|
||||
__ CallStub(&stub);
|
||||
@ -4602,7 +4583,6 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
|
||||
DCHECK(expr->expression()->IsValidReferenceExpression());
|
||||
|
||||
Comment cmnt(masm_, "[ CountOperation");
|
||||
SetSourcePosition(expr->position());
|
||||
|
||||
Property* prop = expr->expression()->AsProperty();
|
||||
LhsKind assign_type = Property::GetAssignType(prop);
|
||||
@ -4753,8 +4733,7 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
|
||||
__ Mov(x1, x0);
|
||||
__ Mov(x0, Smi::FromInt(count_value));
|
||||
|
||||
// Record position before stub call.
|
||||
SetSourcePosition(expr->position());
|
||||
SetExpressionPosition(expr);
|
||||
|
||||
{
|
||||
Assembler::BlockPoolsScope scope(masm_);
|
||||
@ -4981,7 +4960,7 @@ void FullCodeGenerator::EmitLiteralCompareTypeof(Expression* expr,
|
||||
|
||||
void FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) {
|
||||
Comment cmnt(masm_, "[ CompareOperation");
|
||||
SetSourcePosition(expr->position());
|
||||
SetExpressionPosition(expr);
|
||||
|
||||
// Try to generate an optimized comparison with a literal value.
|
||||
// TODO(jbramley): This only checks common values like NaN or undefined.
|
||||
@ -5036,8 +5015,6 @@ void FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) {
|
||||
__ Bind(&slow_case);
|
||||
}
|
||||
|
||||
// Record position and call the compare IC.
|
||||
SetSourcePosition(expr->position());
|
||||
Handle<Code> ic = CodeFactory::CompareIC(
|
||||
isolate(), op, strength(language_mode())).code();
|
||||
CallIC(ic, expr->CompareOperationFeedbackId());
|
||||
@ -5091,6 +5068,8 @@ void FullCodeGenerator::VisitThisFunction(ThisFunction* expr) {
|
||||
|
||||
void FullCodeGenerator::VisitYield(Yield* expr) {
|
||||
Comment cmnt(masm_, "[ Yield");
|
||||
SetExpressionPosition(expr);
|
||||
|
||||
// Evaluate yielded value first; the initial iterator definition depends on
|
||||
// this. It stays on the stack while we update the iterator.
|
||||
VisitForStackValue(expr->expression());
|
||||
|
@ -1617,20 +1617,19 @@ bool PositionsRecorder::WriteRecordedPositions() {
|
||||
EnsureSpace ensure_space(assembler_);
|
||||
assembler_->RecordRelocInfo(RelocInfo::STATEMENT_POSITION,
|
||||
state_.current_statement_position);
|
||||
state_.written_position = state_.current_statement_position;
|
||||
state_.written_statement_position = state_.current_statement_position;
|
||||
written = true;
|
||||
}
|
||||
state_.written_statement_position = state_.current_statement_position;
|
||||
|
||||
// Write the position if it is different from what was written last time and
|
||||
// also different from the statement position that was just written.
|
||||
if (state_.current_position != state_.written_position &&
|
||||
(state_.current_position != state_.written_statement_position ||
|
||||
!written)) {
|
||||
if (state_.current_position != state_.written_position) {
|
||||
EnsureSpace ensure_space(assembler_);
|
||||
assembler_->RecordRelocInfo(RelocInfo::POSITION, state_.current_position);
|
||||
state_.written_position = state_.current_position;
|
||||
written = true;
|
||||
}
|
||||
state_.written_position = state_.current_position;
|
||||
|
||||
// Return whether something was written.
|
||||
return written;
|
||||
@ -1869,7 +1868,6 @@ void Assembler::RecordJSReturn() {
|
||||
|
||||
|
||||
void Assembler::RecordDebugBreakSlot() {
|
||||
positions_recorder()->WriteRecordedPositions();
|
||||
EnsureSpace ensure_space(this);
|
||||
RecordRelocInfo(RelocInfo::DEBUG_BREAK_SLOT);
|
||||
}
|
||||
|
@ -1085,34 +1085,11 @@ class PositionsRecorder BASE_EMBEDDED {
|
||||
// Currently jit_handler_data_ is used to store JITHandler-specific data
|
||||
// over the lifetime of a PositionsRecorder
|
||||
void* jit_handler_data_;
|
||||
friend class PreservePositionScope;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(PositionsRecorder);
|
||||
};
|
||||
|
||||
|
||||
class PreservePositionScope BASE_EMBEDDED {
|
||||
public:
|
||||
explicit PreservePositionScope(PositionsRecorder* positions_recorder)
|
||||
: positions_recorder_(positions_recorder),
|
||||
saved_state_(positions_recorder->state_) {
|
||||
// Reset positions so that previous ones do not accidentally get
|
||||
// recorded within this scope.
|
||||
positions_recorder->state_ = PositionState();
|
||||
}
|
||||
|
||||
~PreservePositionScope() {
|
||||
positions_recorder_->state_ = saved_state_;
|
||||
}
|
||||
|
||||
private:
|
||||
PositionsRecorder* positions_recorder_;
|
||||
const PositionState saved_state_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(PreservePositionScope);
|
||||
};
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Utility functions
|
||||
|
||||
|
@ -1374,31 +1374,6 @@ static void Generate_CallICStub_DebugBreak(MacroAssembler* masm) {
|
||||
}
|
||||
|
||||
|
||||
static void Generate_LoadIC_DebugBreak(MacroAssembler* masm) {
|
||||
DebugCodegen::GenerateLoadICDebugBreak(masm);
|
||||
}
|
||||
|
||||
|
||||
static void Generate_StoreIC_DebugBreak(MacroAssembler* masm) {
|
||||
DebugCodegen::GenerateStoreICDebugBreak(masm);
|
||||
}
|
||||
|
||||
|
||||
static void Generate_KeyedLoadIC_DebugBreak(MacroAssembler* masm) {
|
||||
DebugCodegen::GenerateKeyedLoadICDebugBreak(masm);
|
||||
}
|
||||
|
||||
|
||||
static void Generate_KeyedStoreIC_DebugBreak(MacroAssembler* masm) {
|
||||
DebugCodegen::GenerateKeyedStoreICDebugBreak(masm);
|
||||
}
|
||||
|
||||
|
||||
static void Generate_CompareNilIC_DebugBreak(MacroAssembler* masm) {
|
||||
DebugCodegen::GenerateCompareNilICDebugBreak(masm);
|
||||
}
|
||||
|
||||
|
||||
static void Generate_Return_DebugBreak(MacroAssembler* masm) {
|
||||
DebugCodegen::GenerateReturnDebugBreak(masm);
|
||||
}
|
||||
|
@ -151,16 +151,6 @@ enum BuiltinExtraArguments {
|
||||
DEBUG_BREAK) \
|
||||
V(CallICStub_DebugBreak, CALL_IC, DEBUG_STUB, \
|
||||
DEBUG_BREAK) \
|
||||
V(LoadIC_DebugBreak, LOAD_IC, DEBUG_STUB, \
|
||||
DEBUG_BREAK) \
|
||||
V(KeyedLoadIC_DebugBreak, KEYED_LOAD_IC, DEBUG_STUB, \
|
||||
DEBUG_BREAK) \
|
||||
V(StoreIC_DebugBreak, STORE_IC, DEBUG_STUB, \
|
||||
DEBUG_BREAK) \
|
||||
V(KeyedStoreIC_DebugBreak, KEYED_STORE_IC, DEBUG_STUB, \
|
||||
DEBUG_BREAK) \
|
||||
V(CompareNilIC_DebugBreak, COMPARE_NIL_IC, DEBUG_STUB, \
|
||||
DEBUG_BREAK) \
|
||||
V(Slot_DebugBreak, BUILTIN, DEBUG_STUB, \
|
||||
DEBUG_BREAK) \
|
||||
V(PlainReturn_LiveEdit, BUILTIN, DEBUG_STUB, \
|
||||
|
@ -239,19 +239,5 @@ void CodeGenerator::PrintCode(Handle<Code> code, CompilationInfo* info) {
|
||||
#endif // ENABLE_DISASSEMBLER
|
||||
}
|
||||
|
||||
|
||||
bool CodeGenerator::RecordPositions(MacroAssembler* masm,
|
||||
int pos,
|
||||
bool right_here) {
|
||||
if (pos != RelocInfo::kNoPosition) {
|
||||
masm->positions_recorder()->RecordStatementPosition(pos);
|
||||
masm->positions_recorder()->RecordPosition(pos);
|
||||
if (right_here) {
|
||||
return masm->positions_recorder()->WriteRecordedPositions();
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
} // namespace v8
|
||||
|
@ -84,10 +84,6 @@ class CodeGenerator {
|
||||
// Print the code after compiling it.
|
||||
static void PrintCode(Handle<Code> code, CompilationInfo* info);
|
||||
|
||||
static bool RecordPositions(MacroAssembler* masm,
|
||||
int pos,
|
||||
bool right_here = false);
|
||||
|
||||
private:
|
||||
DISALLOW_COPY_AND_ASSIGN(CodeGenerator);
|
||||
};
|
||||
|
117
src/debug.cc
117
src/debug.cc
@ -84,8 +84,7 @@ BreakLocation::Iterator::Iterator(Handle<DebugInfo> debug_info,
|
||||
~RelocInfo::ModeMask(RelocInfo::CODE_AGE_SEQUENCE)),
|
||||
break_index_(-1),
|
||||
position_(1),
|
||||
statement_position_(1),
|
||||
has_immediate_position_(false) {
|
||||
statement_position_(1) {
|
||||
Next();
|
||||
}
|
||||
|
||||
@ -115,7 +114,6 @@ void BreakLocation::Iterator::Next() {
|
||||
debug_info_->shared()->start_position());
|
||||
DCHECK(position_ >= 0);
|
||||
DCHECK(statement_position_ >= 0);
|
||||
has_immediate_position_ = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -145,25 +143,19 @@ void BreakLocation::Iterator::Next() {
|
||||
break;
|
||||
}
|
||||
|
||||
// Skip below if we only want locations for calls and returns.
|
||||
if (type_ == CALLS_AND_RETURNS) continue;
|
||||
|
||||
// Only break at an inline cache if it has an immediate position attached.
|
||||
if (has_immediate_position_ &&
|
||||
(code->is_inline_cache_stub() && !code->is_binary_op_stub() &&
|
||||
!code->is_compare_ic_stub() && !code->is_to_boolean_ic_stub())) {
|
||||
if (code->kind() == Code::STUB &&
|
||||
CodeStub::GetMajorKey(code) == CodeStub::CallFunction) {
|
||||
break_index_++;
|
||||
break;
|
||||
}
|
||||
if (code->kind() == Code::STUB) {
|
||||
if (RelocInfo::IsDebuggerStatement(rmode())) {
|
||||
break_index_++;
|
||||
break;
|
||||
} else if (CodeStub::GetMajorKey(code) == CodeStub::CallFunction) {
|
||||
break_index_++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Skip below if we only want locations for calls and returns.
|
||||
if (type_ == CALLS_AND_RETURNS) continue;
|
||||
|
||||
if (RelocInfo::IsDebuggerStatement(rmode())) {
|
||||
break_index_++;
|
||||
break;
|
||||
}
|
||||
|
||||
if (RelocInfo::IsDebugBreakSlot(rmode()) && type_ != CALLS_AND_RETURNS) {
|
||||
@ -172,7 +164,6 @@ void BreakLocation::Iterator::Next() {
|
||||
break;
|
||||
}
|
||||
}
|
||||
has_immediate_position_ = false;
|
||||
}
|
||||
|
||||
|
||||
@ -385,28 +376,8 @@ static Handle<Code> DebugBreakForIC(Handle<Code> code, RelocInfo::Mode mode) {
|
||||
// Find the builtin debug break function matching the calling convention
|
||||
// used by the call site.
|
||||
if (code->is_inline_cache_stub()) {
|
||||
switch (code->kind()) {
|
||||
case Code::CALL_IC:
|
||||
return isolate->builtins()->CallICStub_DebugBreak();
|
||||
|
||||
case Code::LOAD_IC:
|
||||
return isolate->builtins()->LoadIC_DebugBreak();
|
||||
|
||||
case Code::STORE_IC:
|
||||
return isolate->builtins()->StoreIC_DebugBreak();
|
||||
|
||||
case Code::KEYED_LOAD_IC:
|
||||
return isolate->builtins()->KeyedLoadIC_DebugBreak();
|
||||
|
||||
case Code::KEYED_STORE_IC:
|
||||
return isolate->builtins()->KeyedStoreIC_DebugBreak();
|
||||
|
||||
case Code::COMPARE_NIL_IC:
|
||||
return isolate->builtins()->CompareNilIC_DebugBreak();
|
||||
|
||||
default:
|
||||
UNREACHABLE();
|
||||
}
|
||||
DCHECK(code->kind() == Code::CALL_IC);
|
||||
return isolate->builtins()->CallICStub_DebugBreak();
|
||||
}
|
||||
if (RelocInfo::IsConstructCall(mode)) {
|
||||
if (code->has_function_cache()) {
|
||||
@ -1258,8 +1229,6 @@ void Debug::PrepareStep(StepAction step_action,
|
||||
Handle<DebugInfo> debug_info = GetDebugInfo(shared);
|
||||
|
||||
// Compute whether or not the target is a call target.
|
||||
bool is_load_or_store = false;
|
||||
bool is_inline_cache_stub = false;
|
||||
bool is_at_restarted_function = false;
|
||||
Handle<Code> call_function_stub;
|
||||
|
||||
@ -1272,8 +1241,6 @@ void Debug::PrepareStep(StepAction step_action,
|
||||
if (thread_local_.restarter_frame_function_pointer_ == NULL) {
|
||||
if (location.IsCodeTarget()) {
|
||||
Handle<Code> target_code = location.CodeTarget();
|
||||
is_inline_cache_stub = target_code->is_inline_cache_stub();
|
||||
is_load_or_store = is_inline_cache_stub && !target_code->is_call_stub();
|
||||
|
||||
// Check if target code is CallFunction stub.
|
||||
Handle<Code> maybe_call_function_stub = target_code;
|
||||
@ -1320,21 +1287,10 @@ void Debug::PrepareStep(StepAction step_action,
|
||||
// Set target frame pointer.
|
||||
ActivateStepOut(frames_it.frame());
|
||||
}
|
||||
} else if (!(is_inline_cache_stub || location.IsConstructCall() ||
|
||||
!call_function_stub.is_null() || is_at_restarted_function) ||
|
||||
step_action == StepNext || step_action == StepMin) {
|
||||
// Step next or step min.
|
||||
return;
|
||||
}
|
||||
|
||||
// Fill the current function with one-shot break points.
|
||||
// If we are stepping into another frame, only fill calls and returns.
|
||||
FloodWithOneShot(function, step_action == StepFrame ? CALLS_AND_RETURNS
|
||||
: ALL_BREAK_LOCATIONS);
|
||||
|
||||
// Remember source position and frame to handle step next.
|
||||
thread_local_.last_statement_position_ =
|
||||
debug_info->code()->SourceStatementPosition(summary.pc());
|
||||
thread_local_.last_fp_ = frame->UnpaddedFP();
|
||||
} else {
|
||||
if (step_action != StepNext && step_action != StepMin) {
|
||||
// If there's restarter frame on top of the stack, just get the pointer
|
||||
// to function which is going to be restarted.
|
||||
if (is_at_restarted_function) {
|
||||
@ -1395,36 +1351,21 @@ void Debug::PrepareStep(StepAction step_action,
|
||||
}
|
||||
}
|
||||
|
||||
// Fill the current function with one-shot break points even for step in on
|
||||
// a call target as the function called might be a native function for
|
||||
// which step in will not stop. It also prepares for stepping in
|
||||
// getters/setters.
|
||||
// If we are stepping into another frame, only fill calls and returns.
|
||||
FloodWithOneShot(function, step_action == StepFrame ? CALLS_AND_RETURNS
|
||||
: ALL_BREAK_LOCATIONS);
|
||||
|
||||
if (is_load_or_store) {
|
||||
// Remember source position and frame to handle step in getter/setter. If
|
||||
// there is a custom getter/setter it will be handled in
|
||||
// Object::Get/SetPropertyWithAccessor, otherwise the step action will be
|
||||
// propagated on the next Debug::Break.
|
||||
thread_local_.last_statement_position_ =
|
||||
debug_info->code()->SourceStatementPosition(summary.pc());
|
||||
thread_local_.last_fp_ = frame->UnpaddedFP();
|
||||
}
|
||||
|
||||
// Step in or Step in min
|
||||
// Step in through construct call requires no changes to the running code.
|
||||
// Step in through getters/setters should already be prepared as well
|
||||
// because caller of this function (Debug::PrepareStep) is expected to
|
||||
// flood the top frame's function with one shot breakpoints.
|
||||
// Step in through CallFunction stub should also be prepared by caller of
|
||||
// this function (Debug::PrepareStep) which should flood target function
|
||||
// with breakpoints.
|
||||
DCHECK(location.IsConstructCall() || is_inline_cache_stub ||
|
||||
!call_function_stub.is_null() || is_at_restarted_function);
|
||||
ActivateStepIn(frame);
|
||||
}
|
||||
|
||||
// Fill the current function with one-shot break points even for step in on
|
||||
// a call target as the function called might be a native function for
|
||||
// which step in will not stop. It also prepares for stepping in
|
||||
// getters/setters.
|
||||
// If we are stepping into another frame, only fill calls and returns.
|
||||
FloodWithOneShot(function, step_action == StepFrame ? CALLS_AND_RETURNS
|
||||
: ALL_BREAK_LOCATIONS);
|
||||
|
||||
// Remember source position and frame to handle step next.
|
||||
thread_local_.last_statement_position_ =
|
||||
debug_info->code()->SourceStatementPosition(summary.pc());
|
||||
thread_local_.last_fp_ = frame->UnpaddedFP();
|
||||
}
|
||||
|
||||
|
||||
|
@ -177,7 +177,6 @@ class BreakLocation {
|
||||
int break_index_;
|
||||
int position_;
|
||||
int statement_position_;
|
||||
bool has_immediate_position_;
|
||||
|
||||
DisallowHeapAllocation no_gc_;
|
||||
|
||||
|
@ -21,269 +21,6 @@
|
||||
namespace v8 {
|
||||
namespace internal {
|
||||
|
||||
void BreakableStatementChecker::Check(Statement* stmt) {
|
||||
Visit(stmt);
|
||||
}
|
||||
|
||||
|
||||
void BreakableStatementChecker::Check(Expression* expr) {
|
||||
Visit(expr);
|
||||
}
|
||||
|
||||
|
||||
void BreakableStatementChecker::VisitVariableDeclaration(
|
||||
VariableDeclaration* decl) {
|
||||
}
|
||||
|
||||
|
||||
void BreakableStatementChecker::VisitFunctionDeclaration(
|
||||
FunctionDeclaration* decl) {
|
||||
}
|
||||
|
||||
|
||||
void BreakableStatementChecker::VisitImportDeclaration(
|
||||
ImportDeclaration* decl) {
|
||||
}
|
||||
|
||||
|
||||
void BreakableStatementChecker::VisitExportDeclaration(
|
||||
ExportDeclaration* decl) {
|
||||
}
|
||||
|
||||
|
||||
void BreakableStatementChecker::VisitBlock(Block* stmt) {
|
||||
}
|
||||
|
||||
|
||||
void BreakableStatementChecker::VisitExpressionStatement(
|
||||
ExpressionStatement* stmt) {
|
||||
// Check if expression is breakable.
|
||||
Visit(stmt->expression());
|
||||
}
|
||||
|
||||
|
||||
void BreakableStatementChecker::VisitEmptyStatement(EmptyStatement* stmt) {
|
||||
}
|
||||
|
||||
|
||||
void BreakableStatementChecker::VisitIfStatement(IfStatement* stmt) {
|
||||
// If the condition is breakable the if statement is breakable.
|
||||
Visit(stmt->condition());
|
||||
}
|
||||
|
||||
|
||||
void BreakableStatementChecker::VisitContinueStatement(
|
||||
ContinueStatement* stmt) {
|
||||
}
|
||||
|
||||
|
||||
void BreakableStatementChecker::VisitBreakStatement(BreakStatement* stmt) {
|
||||
}
|
||||
|
||||
|
||||
void BreakableStatementChecker::VisitReturnStatement(ReturnStatement* stmt) {
|
||||
// Return is breakable if the expression is.
|
||||
Visit(stmt->expression());
|
||||
}
|
||||
|
||||
|
||||
void BreakableStatementChecker::VisitWithStatement(WithStatement* stmt) {
|
||||
Visit(stmt->expression());
|
||||
}
|
||||
|
||||
|
||||
void BreakableStatementChecker::VisitSwitchStatement(SwitchStatement* stmt) {
|
||||
// Switch statements breakable if the tag expression is.
|
||||
Visit(stmt->tag());
|
||||
}
|
||||
|
||||
|
||||
void BreakableStatementChecker::VisitDoWhileStatement(DoWhileStatement* stmt) {
|
||||
// Mark do while as breakable to avoid adding a break slot in front of it.
|
||||
is_breakable_ = true;
|
||||
}
|
||||
|
||||
|
||||
void BreakableStatementChecker::VisitWhileStatement(WhileStatement* stmt) {
|
||||
// Mark while statements breakable if the condition expression is.
|
||||
Visit(stmt->cond());
|
||||
}
|
||||
|
||||
|
||||
void BreakableStatementChecker::VisitForStatement(ForStatement* stmt) {
|
||||
// We set positions for both init and condition, if they exist.
|
||||
if (stmt->cond() != NULL || stmt->init() != NULL) is_breakable_ = true;
|
||||
}
|
||||
|
||||
|
||||
void BreakableStatementChecker::VisitForInStatement(ForInStatement* stmt) {
|
||||
// For-in is breakable because we set the position for the enumerable.
|
||||
is_breakable_ = true;
|
||||
}
|
||||
|
||||
|
||||
void BreakableStatementChecker::VisitForOfStatement(ForOfStatement* stmt) {
|
||||
// For-of is breakable because we set the position for the next() call.
|
||||
is_breakable_ = true;
|
||||
}
|
||||
|
||||
|
||||
void BreakableStatementChecker::VisitTryCatchStatement(
|
||||
TryCatchStatement* stmt) {
|
||||
// Mark try catch as breakable to avoid adding a break slot in front of it.
|
||||
is_breakable_ = true;
|
||||
}
|
||||
|
||||
|
||||
void BreakableStatementChecker::VisitTryFinallyStatement(
|
||||
TryFinallyStatement* stmt) {
|
||||
// Mark try finally as breakable to avoid adding a break slot in front of it.
|
||||
is_breakable_ = true;
|
||||
}
|
||||
|
||||
|
||||
void BreakableStatementChecker::VisitDebuggerStatement(
|
||||
DebuggerStatement* stmt) {
|
||||
// The debugger statement is breakable.
|
||||
is_breakable_ = true;
|
||||
}
|
||||
|
||||
|
||||
void BreakableStatementChecker::VisitCaseClause(CaseClause* clause) {
|
||||
}
|
||||
|
||||
|
||||
void BreakableStatementChecker::VisitFunctionLiteral(FunctionLiteral* expr) {
|
||||
}
|
||||
|
||||
|
||||
void BreakableStatementChecker::VisitClassLiteral(ClassLiteral* expr) {
|
||||
if (expr->extends() != NULL) {
|
||||
Visit(expr->extends());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void BreakableStatementChecker::VisitNativeFunctionLiteral(
|
||||
NativeFunctionLiteral* expr) {
|
||||
}
|
||||
|
||||
|
||||
void BreakableStatementChecker::VisitConditional(Conditional* expr) {
|
||||
}
|
||||
|
||||
|
||||
void BreakableStatementChecker::VisitVariableProxy(VariableProxy* expr) {
|
||||
}
|
||||
|
||||
|
||||
void BreakableStatementChecker::VisitLiteral(Literal* expr) {
|
||||
}
|
||||
|
||||
|
||||
void BreakableStatementChecker::VisitRegExpLiteral(RegExpLiteral* expr) {
|
||||
}
|
||||
|
||||
|
||||
void BreakableStatementChecker::VisitObjectLiteral(ObjectLiteral* expr) {
|
||||
}
|
||||
|
||||
|
||||
void BreakableStatementChecker::VisitArrayLiteral(ArrayLiteral* expr) {
|
||||
}
|
||||
|
||||
|
||||
void BreakableStatementChecker::VisitAssignment(Assignment* expr) {
|
||||
// If assigning to a property (including a global property) the assignment is
|
||||
// breakable.
|
||||
VariableProxy* proxy = expr->target()->AsVariableProxy();
|
||||
Property* prop = expr->target()->AsProperty();
|
||||
if (prop != NULL || (proxy != NULL && proxy->var()->IsUnallocated())) {
|
||||
is_breakable_ = true;
|
||||
return;
|
||||
}
|
||||
|
||||
// Otherwise the assignment is breakable if the assigned value is.
|
||||
Visit(expr->value());
|
||||
}
|
||||
|
||||
|
||||
void BreakableStatementChecker::VisitYield(Yield* expr) {
|
||||
// Yield is breakable if the expression is.
|
||||
Visit(expr->expression());
|
||||
}
|
||||
|
||||
|
||||
void BreakableStatementChecker::VisitThrow(Throw* expr) {
|
||||
// Throw is breakable if the expression is.
|
||||
Visit(expr->exception());
|
||||
}
|
||||
|
||||
|
||||
void BreakableStatementChecker::VisitProperty(Property* expr) {
|
||||
// Property load is breakable.
|
||||
is_breakable_ = true;
|
||||
}
|
||||
|
||||
|
||||
void BreakableStatementChecker::VisitCall(Call* expr) {
|
||||
// Function calls both through IC and call stub are breakable.
|
||||
is_breakable_ = true;
|
||||
}
|
||||
|
||||
|
||||
void BreakableStatementChecker::VisitCallNew(CallNew* expr) {
|
||||
// Function calls through new are breakable.
|
||||
is_breakable_ = true;
|
||||
}
|
||||
|
||||
|
||||
void BreakableStatementChecker::VisitCallRuntime(CallRuntime* expr) {
|
||||
}
|
||||
|
||||
|
||||
void BreakableStatementChecker::VisitUnaryOperation(UnaryOperation* expr) {
|
||||
Visit(expr->expression());
|
||||
}
|
||||
|
||||
|
||||
void BreakableStatementChecker::VisitCountOperation(CountOperation* expr) {
|
||||
Visit(expr->expression());
|
||||
}
|
||||
|
||||
|
||||
void BreakableStatementChecker::VisitBinaryOperation(BinaryOperation* expr) {
|
||||
Visit(expr->left());
|
||||
if (expr->op() != Token::AND &&
|
||||
expr->op() != Token::OR) {
|
||||
Visit(expr->right());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void BreakableStatementChecker::VisitCompareOperation(CompareOperation* expr) {
|
||||
Visit(expr->left());
|
||||
Visit(expr->right());
|
||||
}
|
||||
|
||||
|
||||
void BreakableStatementChecker::VisitSpread(Spread* expr) {
|
||||
Visit(expr->expression());
|
||||
}
|
||||
|
||||
|
||||
void BreakableStatementChecker::VisitThisFunction(ThisFunction* expr) {
|
||||
}
|
||||
|
||||
|
||||
void BreakableStatementChecker::VisitSuperPropertyReference(
|
||||
SuperPropertyReference* expr) {}
|
||||
|
||||
|
||||
void BreakableStatementChecker::VisitSuperCallReference(
|
||||
SuperCallReference* expr) {}
|
||||
|
||||
|
||||
#define __ ACCESS_MASM(masm())
|
||||
|
||||
bool FullCodeGenerator::MakeCode(CompilationInfo* info) {
|
||||
@ -670,38 +407,59 @@ int FullCodeGenerator::DeclareGlobalsFlags() {
|
||||
}
|
||||
|
||||
|
||||
bool RecordStatementPosition(MacroAssembler* masm, int pos) {
|
||||
if (pos == RelocInfo::kNoPosition) return false;
|
||||
masm->positions_recorder()->RecordStatementPosition(pos);
|
||||
masm->positions_recorder()->RecordPosition(pos);
|
||||
return masm->positions_recorder()->WriteRecordedPositions();
|
||||
}
|
||||
|
||||
|
||||
bool RecordPosition(MacroAssembler* masm, int pos) {
|
||||
if (pos == RelocInfo::kNoPosition) return false;
|
||||
masm->positions_recorder()->RecordPosition(pos);
|
||||
return masm->positions_recorder()->WriteRecordedPositions();
|
||||
}
|
||||
|
||||
|
||||
void FullCodeGenerator::SetFunctionPosition(FunctionLiteral* fun) {
|
||||
CodeGenerator::RecordPositions(masm_, fun->start_position());
|
||||
RecordPosition(masm_, fun->start_position());
|
||||
}
|
||||
|
||||
|
||||
void FullCodeGenerator::SetReturnPosition(FunctionLiteral* fun) {
|
||||
CodeGenerator::RecordPositions(masm_, fun->end_position() - 1);
|
||||
RecordStatementPosition(masm_, fun->end_position() - 1);
|
||||
}
|
||||
|
||||
|
||||
void FullCodeGenerator::SetStatementPosition(Statement* stmt) {
|
||||
if (!info_->is_debug()) {
|
||||
CodeGenerator::RecordPositions(masm_, stmt->position());
|
||||
} else {
|
||||
// Check if the statement will be breakable without adding a debug break
|
||||
// slot.
|
||||
BreakableStatementChecker checker(info_->isolate(), zone());
|
||||
checker.Check(stmt);
|
||||
// Record the statement position right here if the statement is not
|
||||
// breakable. For breakable statements the actual recording of the
|
||||
// position will be postponed to the breakable code (typically an IC).
|
||||
bool position_recorded = CodeGenerator::RecordPositions(
|
||||
masm_, stmt->position(), !checker.is_breakable());
|
||||
// If the position recording did record a new position generate a debug
|
||||
// break slot to make the statement breakable.
|
||||
if (position_recorded) {
|
||||
DebugCodegen::GenerateSlot(masm_);
|
||||
}
|
||||
void FullCodeGenerator::SetStatementPosition(
|
||||
Statement* stmt, FullCodeGenerator::InsertBreak insert_break) {
|
||||
if (stmt->position() == RelocInfo::kNoPosition) return;
|
||||
bool recorded = RecordStatementPosition(masm_, stmt->position());
|
||||
if (recorded && insert_break == INSERT_BREAK && info_->is_debug() &&
|
||||
!stmt->IsDebuggerStatement()) {
|
||||
DebugCodegen::GenerateSlot(masm_);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void FullCodeGenerator::SetExpressionPosition(
|
||||
Expression* expr, FullCodeGenerator::InsertBreak insert_break) {
|
||||
if (expr->position() == RelocInfo::kNoPosition) return;
|
||||
bool recorded = RecordPosition(masm_, expr->position());
|
||||
if (recorded && insert_break == INSERT_BREAK && info_->is_debug()) {
|
||||
DebugCodegen::GenerateSlot(masm_);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void FullCodeGenerator::SetExpressionAsStatementPosition(Expression* expr) {
|
||||
if (expr->position() == RelocInfo::kNoPosition) return;
|
||||
bool recorded = RecordStatementPosition(masm_, expr->position());
|
||||
if (recorded && info_->is_debug()) DebugCodegen::GenerateSlot(masm_);
|
||||
}
|
||||
|
||||
|
||||
void FullCodeGenerator::VisitSuperPropertyReference(
|
||||
SuperPropertyReference* super) {
|
||||
__ CallRuntime(Runtime::kThrowUnsupportedSuperError, 0);
|
||||
@ -713,39 +471,6 @@ void FullCodeGenerator::VisitSuperCallReference(SuperCallReference* super) {
|
||||
}
|
||||
|
||||
|
||||
void FullCodeGenerator::SetExpressionPosition(Expression* expr) {
|
||||
if (!info_->is_debug()) {
|
||||
CodeGenerator::RecordPositions(masm_, expr->position());
|
||||
} else {
|
||||
// Check if the expression will be breakable without adding a debug break
|
||||
// slot.
|
||||
BreakableStatementChecker checker(info_->isolate(), zone());
|
||||
checker.Check(expr);
|
||||
// Record a statement position right here if the expression is not
|
||||
// breakable. For breakable expressions the actual recording of the
|
||||
// position will be postponed to the breakable code (typically an IC).
|
||||
// NOTE this will record a statement position for something which might
|
||||
// not be a statement. As stepping in the debugger will only stop at
|
||||
// statement positions this is used for e.g. the condition expression of
|
||||
// a do while loop.
|
||||
bool position_recorded = CodeGenerator::RecordPositions(
|
||||
masm_, expr->position(), !checker.is_breakable());
|
||||
// If the position recording did record a new position generate a debug
|
||||
// break slot to make the statement breakable.
|
||||
if (position_recorded) {
|
||||
DebugCodegen::GenerateSlot(masm_);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void FullCodeGenerator::SetSourcePosition(int pos) {
|
||||
if (pos != RelocInfo::kNoPosition) {
|
||||
masm_->positions_recorder()->RecordPosition(pos);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void FullCodeGenerator::EmitGeneratorNext(CallRuntime* expr) {
|
||||
ZoneList<Expression*>* args = expr->arguments();
|
||||
DCHECK(args->length() == 2);
|
||||
@ -878,7 +603,7 @@ void FullCodeGenerator::VisitArithmeticExpression(BinaryOperation* expr) {
|
||||
VisitForStackValue(left);
|
||||
VisitForAccumulatorValue(right);
|
||||
|
||||
SetSourcePosition(expr->position());
|
||||
SetExpressionPosition(expr);
|
||||
if (ShouldInlineSmiCase(op)) {
|
||||
EmitInlineSmiBinaryOp(expr, op, left, right);
|
||||
} else {
|
||||
@ -1060,7 +785,9 @@ void FullCodeGenerator::VisitWithStatement(WithStatement* stmt) {
|
||||
|
||||
void FullCodeGenerator::VisitDoWhileStatement(DoWhileStatement* stmt) {
|
||||
Comment cmnt(masm_, "[ DoWhileStatement");
|
||||
SetStatementPosition(stmt);
|
||||
// Do not insert break location as we do that below.
|
||||
SetStatementPosition(stmt, SKIP_BREAK);
|
||||
|
||||
Label body, book_keeping;
|
||||
|
||||
Iteration loop_statement(this, stmt);
|
||||
@ -1073,7 +800,9 @@ void FullCodeGenerator::VisitDoWhileStatement(DoWhileStatement* stmt) {
|
||||
// possible to break on the condition.
|
||||
__ bind(loop_statement.continue_label());
|
||||
PrepareForBailoutForId(stmt->ContinueId(), NO_REGISTERS);
|
||||
SetExpressionPosition(stmt->cond());
|
||||
|
||||
// Here is the actual 'while' keyword.
|
||||
SetExpressionAsStatementPosition(stmt->cond());
|
||||
VisitForControl(stmt->cond(),
|
||||
&book_keeping,
|
||||
loop_statement.break_label(),
|
||||
@ -1100,7 +829,7 @@ void FullCodeGenerator::VisitWhileStatement(WhileStatement* stmt) {
|
||||
|
||||
__ bind(&loop);
|
||||
|
||||
SetExpressionPosition(stmt->cond());
|
||||
SetExpressionAsStatementPosition(stmt->cond());
|
||||
VisitForControl(stmt->cond(),
|
||||
&body,
|
||||
loop_statement.break_label(),
|
||||
@ -1124,13 +853,13 @@ void FullCodeGenerator::VisitWhileStatement(WhileStatement* stmt) {
|
||||
|
||||
void FullCodeGenerator::VisitForStatement(ForStatement* stmt) {
|
||||
Comment cmnt(masm_, "[ ForStatement");
|
||||
// Do not insert break location as we do it below.
|
||||
SetStatementPosition(stmt, SKIP_BREAK);
|
||||
|
||||
Label test, body;
|
||||
|
||||
Iteration loop_statement(this, stmt);
|
||||
|
||||
// Set statement position for a break slot before entering the for-body.
|
||||
SetStatementPosition(stmt);
|
||||
|
||||
if (stmt->init() != NULL) {
|
||||
SetStatementPosition(stmt->init());
|
||||
Visit(stmt->init());
|
||||
@ -1151,16 +880,12 @@ void FullCodeGenerator::VisitForStatement(ForStatement* stmt) {
|
||||
Visit(stmt->next());
|
||||
}
|
||||
|
||||
// Emit the statement position here as this is where the for
|
||||
// statement code starts.
|
||||
SetStatementPosition(stmt);
|
||||
|
||||
// Check stack before looping.
|
||||
EmitBackEdgeBookkeeping(stmt, &body);
|
||||
|
||||
__ bind(&test);
|
||||
if (stmt->cond() != NULL) {
|
||||
SetExpressionPosition(stmt->cond());
|
||||
SetExpressionAsStatementPosition(stmt->cond());
|
||||
VisitForControl(stmt->cond(),
|
||||
&body,
|
||||
loop_statement.break_label(),
|
||||
@ -1177,7 +902,6 @@ void FullCodeGenerator::VisitForStatement(ForStatement* stmt) {
|
||||
|
||||
void FullCodeGenerator::VisitForOfStatement(ForOfStatement* stmt) {
|
||||
Comment cmnt(masm_, "[ ForOfStatement");
|
||||
SetStatementPosition(stmt);
|
||||
|
||||
Iteration loop_statement(this, stmt);
|
||||
increment_loop_depth();
|
||||
@ -1189,7 +913,7 @@ void FullCodeGenerator::VisitForOfStatement(ForOfStatement* stmt) {
|
||||
__ bind(loop_statement.continue_label());
|
||||
|
||||
// result = iterator.next()
|
||||
SetExpressionPosition(stmt->next_result());
|
||||
SetExpressionAsStatementPosition(stmt->next_result());
|
||||
VisitForEffect(stmt->next_result());
|
||||
|
||||
// if (result.done) break;
|
||||
@ -1218,7 +942,8 @@ void FullCodeGenerator::VisitForOfStatement(ForOfStatement* stmt) {
|
||||
|
||||
void FullCodeGenerator::VisitTryCatchStatement(TryCatchStatement* stmt) {
|
||||
Comment cmnt(masm_, "[ TryCatchStatement");
|
||||
SetStatementPosition(stmt);
|
||||
SetStatementPosition(stmt, SKIP_BREAK);
|
||||
|
||||
// The try block adds a handler to the exception handler chain before
|
||||
// entering, and removes it again when exiting normally. If an exception
|
||||
// is thrown during execution of the try block, the handler is consumed
|
||||
@ -1271,7 +996,8 @@ void FullCodeGenerator::VisitTryCatchStatement(TryCatchStatement* stmt) {
|
||||
|
||||
void FullCodeGenerator::VisitTryFinallyStatement(TryFinallyStatement* stmt) {
|
||||
Comment cmnt(masm_, "[ TryFinallyStatement");
|
||||
SetStatementPosition(stmt);
|
||||
SetStatementPosition(stmt, SKIP_BREAK);
|
||||
|
||||
// Try finally is compiled by setting up a try-handler on the stack while
|
||||
// executing the try body, and removing it again afterwards.
|
||||
//
|
||||
@ -1487,7 +1213,7 @@ void FullCodeGenerator::VisitNativeFunctionLiteral(
|
||||
void FullCodeGenerator::VisitThrow(Throw* expr) {
|
||||
Comment cmnt(masm_, "[ Throw");
|
||||
VisitForStackValue(expr->exception());
|
||||
SetSourcePosition(expr->position());
|
||||
SetExpressionPosition(expr);
|
||||
__ CallRuntime(Runtime::kThrow, 1);
|
||||
// Never returns here.
|
||||
}
|
||||
|
@ -24,35 +24,6 @@ namespace internal {
|
||||
// Forward declarations.
|
||||
class JumpPatchSite;
|
||||
|
||||
// AST node visitor which can tell whether a given statement will be breakable
|
||||
// when the code is compiled by the full compiler in the debugger. This means
|
||||
// that there will be an IC (load/store/call) in the code generated for the
|
||||
// debugger to piggybag on.
|
||||
class BreakableStatementChecker: public AstVisitor {
|
||||
public:
|
||||
BreakableStatementChecker(Isolate* isolate, Zone* zone)
|
||||
: is_breakable_(false) {
|
||||
InitializeAstVisitor(isolate, zone);
|
||||
}
|
||||
|
||||
void Check(Statement* stmt);
|
||||
void Check(Expression* stmt);
|
||||
|
||||
bool is_breakable() { return is_breakable_; }
|
||||
|
||||
private:
|
||||
// AST node visit functions.
|
||||
#define DECLARE_VISIT(type) virtual void Visit##type(type* node) override;
|
||||
AST_NODE_LIST(DECLARE_VISIT)
|
||||
#undef DECLARE_VISIT
|
||||
|
||||
bool is_breakable_;
|
||||
|
||||
DEFINE_AST_VISITOR_SUBCLASS_MEMBERS();
|
||||
DISALLOW_COPY_AND_ASSIGN(BreakableStatementChecker);
|
||||
};
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Full code generator.
|
||||
|
||||
@ -688,9 +659,21 @@ class FullCodeGenerator: public AstVisitor {
|
||||
|
||||
void SetFunctionPosition(FunctionLiteral* fun);
|
||||
void SetReturnPosition(FunctionLiteral* fun);
|
||||
void SetStatementPosition(Statement* stmt);
|
||||
void SetExpressionPosition(Expression* expr);
|
||||
void SetSourcePosition(int pos);
|
||||
|
||||
enum InsertBreak { INSERT_BREAK, SKIP_BREAK };
|
||||
|
||||
// During stepping we want to be able to break at each statement, but not at
|
||||
// every (sub-)expression. That is why by default we insert breaks at every
|
||||
// statement position, but not at every expression position, unless stated
|
||||
// otherwise.
|
||||
void SetStatementPosition(Statement* stmt,
|
||||
InsertBreak insert_break = INSERT_BREAK);
|
||||
void SetExpressionPosition(Expression* expr,
|
||||
InsertBreak insert_break = SKIP_BREAK);
|
||||
|
||||
// Consider an expression a statement. As such, we also insert a break.
|
||||
// This is used in loop headers where we want to break for each iteration.
|
||||
void SetExpressionAsStatementPosition(Expression* expr);
|
||||
|
||||
// Non-local control flow support.
|
||||
void EnterTryBlock(int handler_index, Label* handler);
|
||||
|
@ -179,50 +179,6 @@ void DebugCodegen::GenerateCallICStubDebugBreak(MacroAssembler* masm) {
|
||||
}
|
||||
|
||||
|
||||
void DebugCodegen::GenerateLoadICDebugBreak(MacroAssembler* masm) {
|
||||
// Register state for IC load call (from ic-ia32.cc).
|
||||
Register receiver = LoadDescriptor::ReceiverRegister();
|
||||
Register name = LoadDescriptor::NameRegister();
|
||||
Register slot = LoadDescriptor::SlotRegister();
|
||||
RegList regs = receiver.bit() | name.bit() | slot.bit();
|
||||
Generate_DebugBreakCallHelper(masm, regs, 0, false);
|
||||
}
|
||||
|
||||
|
||||
void DebugCodegen::GenerateStoreICDebugBreak(MacroAssembler* masm) {
|
||||
// Register state for IC store call (from ic-ia32.cc).
|
||||
Register receiver = StoreDescriptor::ReceiverRegister();
|
||||
Register name = StoreDescriptor::NameRegister();
|
||||
Register value = StoreDescriptor::ValueRegister();
|
||||
RegList regs = receiver.bit() | name.bit() | value.bit();
|
||||
if (FLAG_vector_stores) {
|
||||
regs |= VectorStoreICDescriptor::SlotRegister().bit();
|
||||
}
|
||||
Generate_DebugBreakCallHelper(masm, regs, 0, false);
|
||||
}
|
||||
|
||||
|
||||
void DebugCodegen::GenerateKeyedLoadICDebugBreak(MacroAssembler* masm) {
|
||||
// Register state for keyed IC load call (from ic-ia32.cc).
|
||||
GenerateLoadICDebugBreak(masm);
|
||||
}
|
||||
|
||||
|
||||
void DebugCodegen::GenerateKeyedStoreICDebugBreak(MacroAssembler* masm) {
|
||||
// Register state for keyed IC store call (from ic-ia32.cc).
|
||||
GenerateStoreICDebugBreak(masm);
|
||||
}
|
||||
|
||||
|
||||
void DebugCodegen::GenerateCompareNilICDebugBreak(MacroAssembler* masm) {
|
||||
// Register state for CompareNil IC
|
||||
// ----------- S t a t e -------------
|
||||
// -- eax : value
|
||||
// -----------------------------------
|
||||
Generate_DebugBreakCallHelper(masm, eax.bit(), 0, false);
|
||||
}
|
||||
|
||||
|
||||
void DebugCodegen::GenerateReturnDebugBreak(MacroAssembler* masm) {
|
||||
// Register state just before return from JS function (from codegen-ia32.cc).
|
||||
// ----------- S t a t e -------------
|
||||
@ -283,8 +239,6 @@ void DebugCodegen::GenerateSlot(MacroAssembler* masm) {
|
||||
|
||||
|
||||
void DebugCodegen::GenerateSlotDebugBreak(MacroAssembler* masm) {
|
||||
// In the places where a debug break slot is inserted no registers can contain
|
||||
// object pointers.
|
||||
Generate_DebugBreakCallHelper(masm, 0, 0, true);
|
||||
}
|
||||
|
||||
|
@ -469,7 +469,7 @@ void FullCodeGenerator::EmitReturnSequence() {
|
||||
Label check_exit_codesize;
|
||||
masm_->bind(&check_exit_codesize);
|
||||
#endif
|
||||
SetSourcePosition(function()->end_position() - 1);
|
||||
SetReturnPosition(function());
|
||||
__ RecordJSReturn();
|
||||
// Do not use the leave instruction here because it is too short to
|
||||
// patch with the code required by the debugger.
|
||||
@ -1022,8 +1022,7 @@ void FullCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) {
|
||||
__ bind(&slow_case);
|
||||
}
|
||||
|
||||
// Record position before stub call for type feedback.
|
||||
SetSourcePosition(clause->position());
|
||||
SetExpressionPosition(clause);
|
||||
Handle<Code> ic = CodeFactory::CompareIC(isolate(), Token::EQ_STRICT,
|
||||
strength(language_mode())).code();
|
||||
CallIC(ic, clause->CompareId());
|
||||
@ -1070,9 +1069,9 @@ void FullCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) {
|
||||
|
||||
void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
|
||||
Comment cmnt(masm_, "[ ForInStatement");
|
||||
FeedbackVectorSlot slot = stmt->ForInFeedbackSlot();
|
||||
SetStatementPosition(stmt, SKIP_BREAK);
|
||||
|
||||
SetStatementPosition(stmt);
|
||||
FeedbackVectorSlot slot = stmt->ForInFeedbackSlot();
|
||||
|
||||
Label loop, exit;
|
||||
ForIn loop_statement(this, stmt);
|
||||
@ -1080,7 +1079,7 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
|
||||
|
||||
// Get the object to enumerate over. If the object is null or undefined, skip
|
||||
// over the loop. See ECMA-262 version 5, section 12.6.4.
|
||||
SetExpressionPosition(stmt->enumerable());
|
||||
SetExpressionAsStatementPosition(stmt->enumerable());
|
||||
VisitForAccumulatorValue(stmt->enumerable());
|
||||
__ cmp(eax, isolate()->factory()->undefined_value());
|
||||
__ j(equal, &exit);
|
||||
@ -1175,7 +1174,7 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
|
||||
// Generate code for doing the condition check.
|
||||
PrepareForBailoutForId(stmt->BodyId(), NO_REGISTERS);
|
||||
__ bind(&loop);
|
||||
SetExpressionPosition(stmt->each());
|
||||
SetExpressionAsStatementPosition(stmt->each());
|
||||
|
||||
__ mov(eax, Operand(esp, 0 * kPointerSize)); // Get the current index.
|
||||
__ cmp(eax, Operand(esp, 1 * kPointerSize)); // Compare to the array length.
|
||||
@ -1420,8 +1419,7 @@ void FullCodeGenerator::EmitDynamicLookupFastCase(VariableProxy* proxy,
|
||||
|
||||
|
||||
void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy) {
|
||||
// Record position before possible IC call.
|
||||
SetSourcePosition(proxy->position());
|
||||
SetExpressionPosition(proxy);
|
||||
PrepareForBailoutForId(proxy->BeforeId(), NO_REGISTERS);
|
||||
Variable* var = proxy->var();
|
||||
|
||||
@ -1919,6 +1917,7 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) {
|
||||
DCHECK(expr->target()->IsValidReferenceExpression());
|
||||
|
||||
Comment cmnt(masm_, "[ Assignment");
|
||||
SetExpressionPosition(expr, INSERT_BREAK);
|
||||
|
||||
Property* property = expr->target()->AsProperty();
|
||||
LhsKind assign_type = Property::GetAssignType(property);
|
||||
@ -2008,7 +2007,6 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) {
|
||||
__ push(eax); // Left operand goes on the stack.
|
||||
VisitForAccumulatorValue(expr->value());
|
||||
|
||||
SetSourcePosition(expr->position() + 1);
|
||||
if (ShouldInlineSmiCase(op)) {
|
||||
EmitInlineSmiBinaryOp(expr->binary_operation(),
|
||||
op,
|
||||
@ -2024,8 +2022,7 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) {
|
||||
VisitForAccumulatorValue(expr->value());
|
||||
}
|
||||
|
||||
// Record source position before possible IC call.
|
||||
SetSourcePosition(expr->position());
|
||||
SetExpressionPosition(expr);
|
||||
|
||||
// Store the value.
|
||||
switch (assign_type) {
|
||||
@ -2055,6 +2052,8 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) {
|
||||
|
||||
void FullCodeGenerator::VisitYield(Yield* expr) {
|
||||
Comment cmnt(masm_, "[ Yield");
|
||||
SetExpressionPosition(expr);
|
||||
|
||||
// Evaluate yielded value first; the initial iterator definition depends on
|
||||
// this. It stays on the stack while we update the iterator.
|
||||
VisitForStackValue(expr->expression());
|
||||
@ -2340,7 +2339,7 @@ void FullCodeGenerator::EmitCreateIteratorResult(bool done) {
|
||||
|
||||
|
||||
void FullCodeGenerator::EmitNamedPropertyLoad(Property* prop) {
|
||||
SetSourcePosition(prop->position());
|
||||
SetExpressionPosition(prop);
|
||||
Literal* key = prop->key()->AsLiteral();
|
||||
DCHECK(!key->value()->IsSmi());
|
||||
DCHECK(!prop->IsSuperAccess());
|
||||
@ -2354,7 +2353,7 @@ void FullCodeGenerator::EmitNamedPropertyLoad(Property* prop) {
|
||||
|
||||
void FullCodeGenerator::EmitNamedSuperPropertyLoad(Property* prop) {
|
||||
// Stack: receiver, home_object.
|
||||
SetSourcePosition(prop->position());
|
||||
SetExpressionPosition(prop);
|
||||
Literal* key = prop->key()->AsLiteral();
|
||||
DCHECK(!key->value()->IsSmi());
|
||||
DCHECK(prop->IsSuperAccess());
|
||||
@ -2366,7 +2365,7 @@ void FullCodeGenerator::EmitNamedSuperPropertyLoad(Property* prop) {
|
||||
|
||||
|
||||
void FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) {
|
||||
SetSourcePosition(prop->position());
|
||||
SetExpressionPosition(prop);
|
||||
Handle<Code> ic = CodeFactory::KeyedLoadIC(isolate(), language_mode()).code();
|
||||
__ mov(LoadDescriptor::SlotRegister(),
|
||||
Immediate(SmiFromSlot(prop->PropertyFeedbackSlot())));
|
||||
@ -2376,9 +2375,8 @@ void FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) {
|
||||
|
||||
void FullCodeGenerator::EmitKeyedSuperPropertyLoad(Property* prop) {
|
||||
// Stack: receiver, home_object, key.
|
||||
SetExpressionPosition(prop);
|
||||
__ push(Immediate(Smi::FromInt(language_mode())));
|
||||
SetSourcePosition(prop->position());
|
||||
|
||||
__ CallRuntime(Runtime::kLoadKeyedFromSuper, 4);
|
||||
}
|
||||
|
||||
@ -2738,13 +2736,10 @@ void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) {
|
||||
// Assignment to a property, using a named store IC.
|
||||
// eax : value
|
||||
// esp[0] : receiver
|
||||
|
||||
Property* prop = expr->target()->AsProperty();
|
||||
DCHECK(prop != NULL);
|
||||
DCHECK(prop->key()->IsLiteral());
|
||||
|
||||
// Record source code position before IC call.
|
||||
SetSourcePosition(expr->position());
|
||||
__ mov(StoreDescriptor::NameRegister(), prop->key()->AsLiteral()->value());
|
||||
__ pop(StoreDescriptor::ReceiverRegister());
|
||||
if (FLAG_vector_stores) {
|
||||
@ -2796,8 +2791,6 @@ void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) {
|
||||
__ pop(StoreDescriptor::NameRegister()); // Key.
|
||||
__ pop(StoreDescriptor::ReceiverRegister());
|
||||
DCHECK(StoreDescriptor::ValueRegister().is(eax));
|
||||
// Record source code position before IC call.
|
||||
SetSourcePosition(expr->position());
|
||||
Handle<Code> ic =
|
||||
CodeFactory::KeyedStoreIC(isolate(), language_mode()).code();
|
||||
if (FLAG_vector_stores) {
|
||||
@ -2814,6 +2807,8 @@ void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) {
|
||||
|
||||
void FullCodeGenerator::VisitProperty(Property* expr) {
|
||||
Comment cmnt(masm_, "[ Property");
|
||||
SetExpressionPosition(expr);
|
||||
|
||||
Expression* key = expr->key();
|
||||
|
||||
if (key->IsPropertyName()) {
|
||||
@ -2886,12 +2881,12 @@ void FullCodeGenerator::EmitCallWithLoadIC(Call* expr) {
|
||||
|
||||
|
||||
void FullCodeGenerator::EmitSuperCallWithLoadIC(Call* expr) {
|
||||
SetExpressionPosition(expr);
|
||||
Expression* callee = expr->expression();
|
||||
DCHECK(callee->IsProperty());
|
||||
Property* prop = callee->AsProperty();
|
||||
DCHECK(prop->IsSuperAccess());
|
||||
|
||||
SetSourcePosition(prop->position());
|
||||
Literal* key = prop->key()->AsLiteral();
|
||||
DCHECK(!key->value()->IsSmi());
|
||||
// Load the function from the receiver.
|
||||
@ -2951,7 +2946,7 @@ void FullCodeGenerator::EmitKeyedSuperCallWithLoadIC(Call* expr) {
|
||||
Property* prop = callee->AsProperty();
|
||||
DCHECK(prop->IsSuperAccess());
|
||||
|
||||
SetSourcePosition(prop->position());
|
||||
SetExpressionPosition(prop);
|
||||
// Load the function from the receiver.
|
||||
SuperPropertyReference* super_ref = prop->obj()->AsSuperPropertyReference();
|
||||
VisitForStackValue(super_ref->home_object());
|
||||
@ -2984,14 +2979,11 @@ void FullCodeGenerator::EmitCall(Call* expr, CallICState::CallType call_type) {
|
||||
// Load the arguments.
|
||||
ZoneList<Expression*>* args = expr->arguments();
|
||||
int arg_count = args->length();
|
||||
{ PreservePositionScope scope(masm()->positions_recorder());
|
||||
for (int i = 0; i < arg_count; i++) {
|
||||
VisitForStackValue(args->at(i));
|
||||
}
|
||||
for (int i = 0; i < arg_count; i++) {
|
||||
VisitForStackValue(args->at(i));
|
||||
}
|
||||
|
||||
// Record source position of the IC call.
|
||||
SetSourcePosition(expr->position());
|
||||
SetExpressionPosition(expr);
|
||||
Handle<Code> ic = CodeFactory::CallIC(isolate(), arg_count, call_type).code();
|
||||
__ Move(edx, Immediate(SmiFromSlot(expr->CallFeedbackICSlot())));
|
||||
__ mov(edi, Operand(esp, (arg_count + 1) * kPointerSize));
|
||||
@ -3051,13 +3043,11 @@ void FullCodeGenerator::PushCalleeAndWithBaseObject(Call* expr) {
|
||||
VariableProxy* callee = expr->expression()->AsVariableProxy();
|
||||
if (callee->var()->IsLookupSlot()) {
|
||||
Label slow, done;
|
||||
SetSourcePosition(callee->position());
|
||||
{
|
||||
PreservePositionScope scope(masm()->positions_recorder());
|
||||
// Generate code for loading from variables potentially shadowed by
|
||||
// eval-introduced variables.
|
||||
EmitDynamicLookupFastCase(callee, NOT_INSIDE_TYPEOF, &slow, &done);
|
||||
}
|
||||
SetExpressionPosition(callee);
|
||||
// Generate code for loading from variables potentially shadowed by
|
||||
// eval-introduced variables.
|
||||
EmitDynamicLookupFastCase(callee, NOT_INSIDE_TYPEOF, &slow, &done);
|
||||
|
||||
__ bind(&slow);
|
||||
// Call the runtime to find the function to call (returned in eax) and
|
||||
// the object holding it (returned in edx).
|
||||
@ -3106,26 +3096,25 @@ void FullCodeGenerator::VisitCall(Call* expr) {
|
||||
// function using the given arguments.
|
||||
ZoneList<Expression*>* args = expr->arguments();
|
||||
int arg_count = args->length();
|
||||
{ PreservePositionScope pos_scope(masm()->positions_recorder());
|
||||
PushCalleeAndWithBaseObject(expr);
|
||||
|
||||
// Push the arguments.
|
||||
for (int i = 0; i < arg_count; i++) {
|
||||
VisitForStackValue(args->at(i));
|
||||
}
|
||||
PushCalleeAndWithBaseObject(expr);
|
||||
|
||||
// Push a copy of the function (found below the arguments) and
|
||||
// resolve eval.
|
||||
__ push(Operand(esp, (arg_count + 1) * kPointerSize));
|
||||
EmitResolvePossiblyDirectEval(arg_count);
|
||||
|
||||
// Touch up the stack with the resolved function.
|
||||
__ mov(Operand(esp, (arg_count + 1) * kPointerSize), eax);
|
||||
|
||||
PrepareForBailoutForId(expr->EvalId(), NO_REGISTERS);
|
||||
// Push the arguments.
|
||||
for (int i = 0; i < arg_count; i++) {
|
||||
VisitForStackValue(args->at(i));
|
||||
}
|
||||
// Record source position for debugger.
|
||||
SetSourcePosition(expr->position());
|
||||
|
||||
// Push a copy of the function (found below the arguments) and
|
||||
// resolve eval.
|
||||
__ push(Operand(esp, (arg_count + 1) * kPointerSize));
|
||||
EmitResolvePossiblyDirectEval(arg_count);
|
||||
|
||||
// Touch up the stack with the resolved function.
|
||||
__ mov(Operand(esp, (arg_count + 1) * kPointerSize), eax);
|
||||
|
||||
PrepareForBailoutForId(expr->EvalId(), NO_REGISTERS);
|
||||
|
||||
SetExpressionPosition(expr);
|
||||
CallFunctionStub stub(isolate(), arg_count, NO_CALL_FUNCTION_FLAGS);
|
||||
__ mov(edi, Operand(esp, (arg_count + 1) * kPointerSize));
|
||||
__ CallStub(&stub);
|
||||
@ -3150,10 +3139,7 @@ void FullCodeGenerator::VisitCall(Call* expr) {
|
||||
EmitKeyedSuperCallWithLoadIC(expr);
|
||||
}
|
||||
} else {
|
||||
{
|
||||
PreservePositionScope scope(masm()->positions_recorder());
|
||||
VisitForStackValue(property->obj());
|
||||
}
|
||||
VisitForStackValue(property->obj());
|
||||
if (is_named_call) {
|
||||
EmitCallWithLoadIC(expr);
|
||||
} else {
|
||||
@ -3165,9 +3151,7 @@ void FullCodeGenerator::VisitCall(Call* expr) {
|
||||
} else {
|
||||
DCHECK(call_type == Call::OTHER_CALL);
|
||||
// Call to an arbitrary expression not handled specially above.
|
||||
{ PreservePositionScope scope(masm()->positions_recorder());
|
||||
VisitForStackValue(callee);
|
||||
}
|
||||
VisitForStackValue(callee);
|
||||
__ push(Immediate(isolate()->factory()->undefined_value()));
|
||||
// Emit function call.
|
||||
EmitCall(expr);
|
||||
@ -3201,7 +3185,7 @@ void FullCodeGenerator::VisitCallNew(CallNew* expr) {
|
||||
|
||||
// Call the construct call builtin that handles allocation and
|
||||
// constructor invocation.
|
||||
SetSourcePosition(expr->position());
|
||||
SetExpressionPosition(expr);
|
||||
|
||||
// Load function and argument count into edi and eax.
|
||||
__ Move(eax, Immediate(arg_count));
|
||||
@ -3244,7 +3228,7 @@ void FullCodeGenerator::EmitSuperConstructorCall(Call* expr) {
|
||||
|
||||
// Call the construct call builtin that handles allocation and
|
||||
// constructor invocation.
|
||||
SetSourcePosition(expr->position());
|
||||
SetExpressionPosition(expr);
|
||||
|
||||
// Load function and argument count into edi and eax.
|
||||
__ Move(eax, Immediate(arg_count));
|
||||
@ -4667,8 +4651,7 @@ void FullCodeGenerator::EmitCallJSRuntimeFunction(CallRuntime* expr) {
|
||||
ZoneList<Expression*>* args = expr->arguments();
|
||||
int arg_count = args->length();
|
||||
|
||||
// Record source position of the IC call.
|
||||
SetSourcePosition(expr->position());
|
||||
SetExpressionPosition(expr);
|
||||
CallFunctionStub stub(isolate(), arg_count, NO_CALL_FUNCTION_FLAGS);
|
||||
__ mov(edi, Operand(esp, (arg_count + 1) * kPointerSize));
|
||||
__ CallStub(&stub);
|
||||
@ -4848,7 +4831,6 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
|
||||
DCHECK(expr->expression()->IsValidReferenceExpression());
|
||||
|
||||
Comment cmnt(masm_, "[ CountOperation");
|
||||
SetSourcePosition(expr->position());
|
||||
|
||||
Property* prop = expr->expression()->AsProperty();
|
||||
LhsKind assign_type = Property::GetAssignType(prop);
|
||||
@ -4999,8 +4981,7 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
|
||||
}
|
||||
}
|
||||
|
||||
// Record position before stub call.
|
||||
SetSourcePosition(expr->position());
|
||||
SetExpressionPosition(expr);
|
||||
|
||||
// Call stub for +1/-1.
|
||||
__ bind(&stub_call);
|
||||
@ -5221,7 +5202,7 @@ void FullCodeGenerator::EmitLiteralCompareTypeof(Expression* expr,
|
||||
|
||||
void FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) {
|
||||
Comment cmnt(masm_, "[ CompareOperation");
|
||||
SetSourcePosition(expr->position());
|
||||
SetExpressionPosition(expr);
|
||||
|
||||
// First we try a fast inlined version of the compare when one of
|
||||
// the operands is a literal.
|
||||
@ -5275,8 +5256,6 @@ void FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) {
|
||||
__ bind(&slow_case);
|
||||
}
|
||||
|
||||
// Record position and call the compare IC.
|
||||
SetSourcePosition(expr->position());
|
||||
Handle<Code> ic = CodeFactory::CompareIC(
|
||||
isolate(), op, strength(language_mode())).code();
|
||||
CallIC(ic, expr->CompareOperationFeedbackId());
|
||||
|
@ -150,49 +150,6 @@ void DebugCodegen::GenerateCallICStubDebugBreak(MacroAssembler* masm) {
|
||||
}
|
||||
|
||||
|
||||
void DebugCodegen::GenerateLoadICDebugBreak(MacroAssembler* masm) {
|
||||
Register receiver = LoadDescriptor::ReceiverRegister();
|
||||
Register name = LoadDescriptor::NameRegister();
|
||||
Register slot = LoadDescriptor::SlotRegister();
|
||||
RegList regs = receiver.bit() | name.bit() | slot.bit();
|
||||
Generate_DebugBreakCallHelper(masm, regs, 0);
|
||||
}
|
||||
|
||||
|
||||
void DebugCodegen::GenerateStoreICDebugBreak(MacroAssembler* masm) {
|
||||
// Calling convention for IC store (from ic-mips.cc).
|
||||
Register receiver = StoreDescriptor::ReceiverRegister();
|
||||
Register name = StoreDescriptor::NameRegister();
|
||||
Register value = StoreDescriptor::ValueRegister();
|
||||
RegList regs = receiver.bit() | name.bit() | value.bit();
|
||||
if (FLAG_vector_stores) {
|
||||
regs |= VectorStoreICDescriptor::SlotRegister().bit();
|
||||
}
|
||||
Generate_DebugBreakCallHelper(masm, regs, 0);
|
||||
}
|
||||
|
||||
|
||||
void DebugCodegen::GenerateKeyedLoadICDebugBreak(MacroAssembler* masm) {
|
||||
// Calling convention for keyed IC load (from ic-mips.cc).
|
||||
GenerateLoadICDebugBreak(masm);
|
||||
}
|
||||
|
||||
|
||||
void DebugCodegen::GenerateKeyedStoreICDebugBreak(MacroAssembler* masm) {
|
||||
// Calling convention for IC keyed store call (from ic-mips.cc).
|
||||
GenerateStoreICDebugBreak(masm);
|
||||
}
|
||||
|
||||
|
||||
void DebugCodegen::GenerateCompareNilICDebugBreak(MacroAssembler* masm) {
|
||||
// Register state for CompareNil IC
|
||||
// ----------- S t a t e -------------
|
||||
// -- a0 : value
|
||||
// -----------------------------------
|
||||
Generate_DebugBreakCallHelper(masm, a0.bit(), 0);
|
||||
}
|
||||
|
||||
|
||||
void DebugCodegen::GenerateReturnDebugBreak(MacroAssembler* masm) {
|
||||
// In places other than IC call sites it is expected that v0 is TOS which
|
||||
// is an object - this is not generally the case so this should be used with
|
||||
|
@ -506,7 +506,7 @@ void FullCodeGenerator::EmitReturnSequence() {
|
||||
// tool from instrumenting as we rely on the code size here.
|
||||
int32_t arg_count = info_->scope()->num_parameters() + 1;
|
||||
int32_t sp_delta = arg_count * kPointerSize;
|
||||
CodeGenerator::RecordPositions(masm_, function()->end_position() - 1);
|
||||
SetReturnPosition(function());
|
||||
__ RecordJSReturn();
|
||||
masm_->mov(sp, fp);
|
||||
int no_frame_start = masm_->pc_offset();
|
||||
@ -1082,7 +1082,7 @@ void FullCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) {
|
||||
}
|
||||
|
||||
// Record position before stub call for type feedback.
|
||||
SetSourcePosition(clause->position());
|
||||
SetExpressionPosition(clause);
|
||||
Handle<Code> ic = CodeFactory::CompareIC(isolate(), Token::EQ_STRICT,
|
||||
strength(language_mode())).code();
|
||||
CallIC(ic, clause->CompareId());
|
||||
@ -1128,8 +1128,9 @@ void FullCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) {
|
||||
|
||||
void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
|
||||
Comment cmnt(masm_, "[ ForInStatement");
|
||||
SetStatementPosition(stmt, SKIP_BREAK);
|
||||
|
||||
FeedbackVectorSlot slot = stmt->ForInFeedbackSlot();
|
||||
SetStatementPosition(stmt);
|
||||
|
||||
Label loop, exit;
|
||||
ForIn loop_statement(this, stmt);
|
||||
@ -1137,7 +1138,7 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
|
||||
|
||||
// Get the object to enumerate over. If the object is null or undefined, skip
|
||||
// over the loop. See ECMA-262 version 5, section 12.6.4.
|
||||
SetExpressionPosition(stmt->enumerable());
|
||||
SetExpressionAsStatementPosition(stmt->enumerable());
|
||||
VisitForAccumulatorValue(stmt->enumerable());
|
||||
__ mov(a0, result_register()); // Result as param to InvokeBuiltin below.
|
||||
__ LoadRoot(at, Heap::kUndefinedValueRootIndex);
|
||||
@ -1237,7 +1238,7 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
|
||||
// Generate code for doing the condition check.
|
||||
PrepareForBailoutForId(stmt->BodyId(), NO_REGISTERS);
|
||||
__ bind(&loop);
|
||||
SetExpressionPosition(stmt->each());
|
||||
SetExpressionAsStatementPosition(stmt->each());
|
||||
|
||||
// Load the current count to a0, load the length to a1.
|
||||
__ lw(a0, MemOperand(sp, 0 * kPointerSize));
|
||||
@ -1483,7 +1484,7 @@ void FullCodeGenerator::EmitDynamicLookupFastCase(VariableProxy* proxy,
|
||||
|
||||
void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy) {
|
||||
// Record position before possible IC call.
|
||||
SetSourcePosition(proxy->position());
|
||||
SetExpressionPosition(proxy);
|
||||
PrepareForBailoutForId(proxy->BeforeId(), NO_REGISTERS);
|
||||
Variable* var = proxy->var();
|
||||
|
||||
@ -1980,6 +1981,7 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) {
|
||||
DCHECK(expr->target()->IsValidReferenceExpression());
|
||||
|
||||
Comment cmnt(masm_, "[ Assignment");
|
||||
SetExpressionPosition(expr, INSERT_BREAK);
|
||||
|
||||
Property* property = expr->target()->AsProperty();
|
||||
LhsKind assign_type = Property::GetAssignType(property);
|
||||
@ -2073,7 +2075,6 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) {
|
||||
__ push(v0); // Left operand goes on the stack.
|
||||
VisitForAccumulatorValue(expr->value());
|
||||
|
||||
SetSourcePosition(expr->position() + 1);
|
||||
AccumulatorValueContext context(this);
|
||||
if (ShouldInlineSmiCase(op)) {
|
||||
EmitInlineSmiBinaryOp(expr->binary_operation(),
|
||||
@ -2090,8 +2091,7 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) {
|
||||
VisitForAccumulatorValue(expr->value());
|
||||
}
|
||||
|
||||
// Record source position before possible IC call.
|
||||
SetSourcePosition(expr->position());
|
||||
SetExpressionPosition(expr);
|
||||
|
||||
// Store the value.
|
||||
switch (assign_type) {
|
||||
@ -2121,6 +2121,8 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) {
|
||||
|
||||
void FullCodeGenerator::VisitYield(Yield* expr) {
|
||||
Comment cmnt(masm_, "[ Yield");
|
||||
SetExpressionPosition(expr);
|
||||
|
||||
// Evaluate yielded value first; the initial iterator definition depends on
|
||||
// this. It stays on the stack while we update the iterator.
|
||||
VisitForStackValue(expr->expression());
|
||||
@ -2408,7 +2410,7 @@ void FullCodeGenerator::EmitCreateIteratorResult(bool done) {
|
||||
|
||||
|
||||
void FullCodeGenerator::EmitNamedPropertyLoad(Property* prop) {
|
||||
SetSourcePosition(prop->position());
|
||||
SetExpressionPosition(prop);
|
||||
Literal* key = prop->key()->AsLiteral();
|
||||
DCHECK(!prop->IsSuperAccess());
|
||||
|
||||
@ -2421,7 +2423,8 @@ void FullCodeGenerator::EmitNamedPropertyLoad(Property* prop) {
|
||||
|
||||
void FullCodeGenerator::EmitNamedSuperPropertyLoad(Property* prop) {
|
||||
// Stack: receiver, home_object.
|
||||
SetSourcePosition(prop->position());
|
||||
SetExpressionPosition(prop);
|
||||
|
||||
Literal* key = prop->key()->AsLiteral();
|
||||
DCHECK(!key->value()->IsSmi());
|
||||
DCHECK(prop->IsSuperAccess());
|
||||
@ -2433,7 +2436,7 @@ void FullCodeGenerator::EmitNamedSuperPropertyLoad(Property* prop) {
|
||||
|
||||
|
||||
void FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) {
|
||||
SetSourcePosition(prop->position());
|
||||
SetExpressionPosition(prop);
|
||||
Handle<Code> ic = CodeFactory::KeyedLoadIC(isolate(), language_mode()).code();
|
||||
__ li(LoadDescriptor::SlotRegister(),
|
||||
Operand(SmiFromSlot(prop->PropertyFeedbackSlot())));
|
||||
@ -2443,9 +2446,8 @@ void FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) {
|
||||
|
||||
void FullCodeGenerator::EmitKeyedSuperPropertyLoad(Property* prop) {
|
||||
// Stack: receiver, home_object, key.
|
||||
SetExpressionPosition(prop);
|
||||
__ Push(Smi::FromInt(language_mode()));
|
||||
SetSourcePosition(prop->position());
|
||||
|
||||
__ CallRuntime(Runtime::kLoadKeyedFromSuper, 4);
|
||||
}
|
||||
|
||||
@ -2816,8 +2818,6 @@ void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) {
|
||||
DCHECK(prop != NULL);
|
||||
DCHECK(prop->key()->IsLiteral());
|
||||
|
||||
// Record source code position before IC call.
|
||||
SetSourcePosition(expr->position());
|
||||
__ mov(StoreDescriptor::ValueRegister(), result_register());
|
||||
__ li(StoreDescriptor::NameRegister(),
|
||||
Operand(prop->key()->AsLiteral()->value()));
|
||||
@ -2866,9 +2866,6 @@ void FullCodeGenerator::EmitKeyedSuperPropertyStore(Property* prop) {
|
||||
|
||||
void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) {
|
||||
// Assignment to a property, using a keyed store IC.
|
||||
|
||||
// Record source code position before IC call.
|
||||
SetSourcePosition(expr->position());
|
||||
// Call keyed store IC.
|
||||
// The arguments are:
|
||||
// - a0 is the value,
|
||||
@ -2894,6 +2891,8 @@ void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) {
|
||||
|
||||
void FullCodeGenerator::VisitProperty(Property* expr) {
|
||||
Comment cmnt(masm_, "[ Property");
|
||||
SetExpressionPosition(expr);
|
||||
|
||||
Expression* key = expr->key();
|
||||
|
||||
if (key->IsPropertyName()) {
|
||||
@ -2969,12 +2968,12 @@ void FullCodeGenerator::EmitCallWithLoadIC(Call* expr) {
|
||||
|
||||
|
||||
void FullCodeGenerator::EmitSuperCallWithLoadIC(Call* expr) {
|
||||
SetExpressionPosition(expr);
|
||||
Expression* callee = expr->expression();
|
||||
DCHECK(callee->IsProperty());
|
||||
Property* prop = callee->AsProperty();
|
||||
DCHECK(prop->IsSuperAccess());
|
||||
|
||||
SetSourcePosition(prop->position());
|
||||
Literal* key = prop->key()->AsLiteral();
|
||||
DCHECK(!key->value()->IsSmi());
|
||||
// Load the function from the receiver.
|
||||
@ -3036,7 +3035,7 @@ void FullCodeGenerator::EmitKeyedSuperCallWithLoadIC(Call* expr) {
|
||||
Property* prop = callee->AsProperty();
|
||||
DCHECK(prop->IsSuperAccess());
|
||||
|
||||
SetSourcePosition(prop->position());
|
||||
SetExpressionPosition(prop);
|
||||
// Load the function from the receiver.
|
||||
const Register scratch = a1;
|
||||
SuperPropertyReference* super_ref = prop->obj()->AsSuperPropertyReference();
|
||||
@ -3070,14 +3069,12 @@ void FullCodeGenerator::EmitCall(Call* expr, CallICState::CallType call_type) {
|
||||
// Load the arguments.
|
||||
ZoneList<Expression*>* args = expr->arguments();
|
||||
int arg_count = args->length();
|
||||
{ PreservePositionScope scope(masm()->positions_recorder());
|
||||
for (int i = 0; i < arg_count; i++) {
|
||||
VisitForStackValue(args->at(i));
|
||||
}
|
||||
for (int i = 0; i < arg_count; i++) {
|
||||
VisitForStackValue(args->at(i));
|
||||
}
|
||||
|
||||
// Record source position of the IC call.
|
||||
SetSourcePosition(expr->position());
|
||||
SetExpressionPosition(expr);
|
||||
Handle<Code> ic = CodeFactory::CallIC(isolate(), arg_count, call_type).code();
|
||||
__ li(a3, Operand(SmiFromSlot(expr->CallFeedbackICSlot())));
|
||||
__ lw(a1, MemOperand(sp, (arg_count + 1) * kPointerSize));
|
||||
@ -3136,13 +3133,11 @@ void FullCodeGenerator::PushCalleeAndWithBaseObject(Call* expr) {
|
||||
VariableProxy* callee = expr->expression()->AsVariableProxy();
|
||||
if (callee->var()->IsLookupSlot()) {
|
||||
Label slow, done;
|
||||
SetSourcePosition(callee->position());
|
||||
{
|
||||
PreservePositionScope scope(masm()->positions_recorder());
|
||||
// Generate code for loading from variables potentially shadowed
|
||||
// by eval-introduced variables.
|
||||
EmitDynamicLookupFastCase(callee, NOT_INSIDE_TYPEOF, &slow, &done);
|
||||
}
|
||||
|
||||
SetExpressionPosition(callee);
|
||||
// Generate code for loading from variables potentially shadowed by
|
||||
// eval-introduced variables.
|
||||
EmitDynamicLookupFastCase(callee, NOT_INSIDE_TYPEOF, &slow, &done);
|
||||
|
||||
__ bind(&slow);
|
||||
// Call the runtime to find the function to call (returned in v0)
|
||||
@ -3195,8 +3190,6 @@ void FullCodeGenerator::VisitCall(Call* expr) {
|
||||
// function using the given arguments.
|
||||
ZoneList<Expression*>* args = expr->arguments();
|
||||
int arg_count = args->length();
|
||||
|
||||
{ PreservePositionScope pos_scope(masm()->positions_recorder());
|
||||
PushCalleeAndWithBaseObject(expr);
|
||||
|
||||
// Push the arguments.
|
||||
@ -3214,9 +3207,8 @@ void FullCodeGenerator::VisitCall(Call* expr) {
|
||||
__ sw(v0, MemOperand(sp, (arg_count + 1) * kPointerSize));
|
||||
|
||||
PrepareForBailoutForId(expr->EvalId(), NO_REGISTERS);
|
||||
}
|
||||
// Record source position for debugger.
|
||||
SetSourcePosition(expr->position());
|
||||
SetExpressionPosition(expr);
|
||||
CallFunctionStub stub(isolate(), arg_count, NO_CALL_FUNCTION_FLAGS);
|
||||
__ lw(a1, MemOperand(sp, (arg_count + 1) * kPointerSize));
|
||||
__ CallStub(&stub);
|
||||
@ -3240,10 +3232,7 @@ void FullCodeGenerator::VisitCall(Call* expr) {
|
||||
EmitKeyedSuperCallWithLoadIC(expr);
|
||||
}
|
||||
} else {
|
||||
{
|
||||
PreservePositionScope scope(masm()->positions_recorder());
|
||||
VisitForStackValue(property->obj());
|
||||
}
|
||||
if (is_named_call) {
|
||||
EmitCallWithLoadIC(expr);
|
||||
} else {
|
||||
@ -3255,9 +3244,7 @@ void FullCodeGenerator::VisitCall(Call* expr) {
|
||||
} else {
|
||||
DCHECK(call_type == Call::OTHER_CALL);
|
||||
// Call to an arbitrary expression not handled specially above.
|
||||
{ PreservePositionScope scope(masm()->positions_recorder());
|
||||
VisitForStackValue(callee);
|
||||
}
|
||||
__ LoadRoot(a1, Heap::kUndefinedValueRootIndex);
|
||||
__ push(a1);
|
||||
// Emit function call.
|
||||
@ -3292,7 +3279,7 @@ void FullCodeGenerator::VisitCallNew(CallNew* expr) {
|
||||
|
||||
// Call the construct call builtin that handles allocation and
|
||||
// constructor invocation.
|
||||
SetSourcePosition(expr->position());
|
||||
SetExpressionPosition(expr);
|
||||
|
||||
// Load function and argument count into a1 and a0.
|
||||
__ li(a0, Operand(arg_count));
|
||||
@ -3335,7 +3322,7 @@ void FullCodeGenerator::EmitSuperConstructorCall(Call* expr) {
|
||||
|
||||
// Call the construct call builtin that handles allocation and
|
||||
// constructor invocation.
|
||||
SetSourcePosition(expr->position());
|
||||
SetExpressionPosition(expr);
|
||||
|
||||
// Load function and argument count into a1 and a0.
|
||||
__ li(a0, Operand(arg_count));
|
||||
@ -4749,8 +4736,7 @@ void FullCodeGenerator::EmitCallJSRuntimeFunction(CallRuntime* expr) {
|
||||
ZoneList<Expression*>* args = expr->arguments();
|
||||
int arg_count = args->length();
|
||||
|
||||
// Record source position of the IC call.
|
||||
SetSourcePosition(expr->position());
|
||||
SetExpressionPosition(expr);
|
||||
CallFunctionStub stub(isolate(), arg_count, NO_CALL_FUNCTION_FLAGS);
|
||||
__ lw(a1, MemOperand(sp, (arg_count + 1) * kPointerSize));
|
||||
__ CallStub(&stub);
|
||||
@ -4928,7 +4914,6 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
|
||||
DCHECK(expr->expression()->IsValidReferenceExpression());
|
||||
|
||||
Comment cmnt(masm_, "[ CountOperation");
|
||||
SetSourcePosition(expr->position());
|
||||
|
||||
Property* prop = expr->expression()->AsProperty();
|
||||
LhsKind assign_type = Property::GetAssignType(prop);
|
||||
@ -5085,8 +5070,8 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
|
||||
__ mov(a1, v0);
|
||||
__ li(a0, Operand(Smi::FromInt(count_value)));
|
||||
|
||||
// Record position before stub call.
|
||||
SetSourcePosition(expr->position());
|
||||
SetExpressionPosition(expr);
|
||||
|
||||
|
||||
Handle<Code> code = CodeFactory::BinaryOpIC(isolate(), Token::ADD,
|
||||
strength(language_mode())).code();
|
||||
@ -5302,7 +5287,7 @@ void FullCodeGenerator::EmitLiteralCompareTypeof(Expression* expr,
|
||||
|
||||
void FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) {
|
||||
Comment cmnt(masm_, "[ CompareOperation");
|
||||
SetSourcePosition(expr->position());
|
||||
SetExpressionPosition(expr);
|
||||
|
||||
// First we try a fast inlined version of the compare when one of
|
||||
// the operands is a literal.
|
||||
@ -5353,8 +5338,7 @@ void FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) {
|
||||
Split(cc, a1, Operand(a0), if_true, if_false, NULL);
|
||||
__ bind(&slow_case);
|
||||
}
|
||||
// Record position and call the compare IC.
|
||||
SetSourcePosition(expr->position());
|
||||
|
||||
Handle<Code> ic = CodeFactory::CompareIC(
|
||||
isolate(), op, strength(language_mode())).code();
|
||||
CallIC(ic, expr->CompareOperationFeedbackId());
|
||||
|
@ -153,48 +153,6 @@ void DebugCodegen::GenerateCallICStubDebugBreak(MacroAssembler* masm) {
|
||||
}
|
||||
|
||||
|
||||
void DebugCodegen::GenerateLoadICDebugBreak(MacroAssembler* masm) {
|
||||
Register receiver = LoadDescriptor::ReceiverRegister();
|
||||
Register name = LoadDescriptor::NameRegister();
|
||||
Register slot = LoadDescriptor::SlotRegister();
|
||||
RegList regs = receiver.bit() | name.bit() | slot.bit();
|
||||
Generate_DebugBreakCallHelper(masm, regs, 0);
|
||||
}
|
||||
|
||||
|
||||
void DebugCodegen::GenerateStoreICDebugBreak(MacroAssembler* masm) {
|
||||
Register receiver = StoreDescriptor::ReceiverRegister();
|
||||
Register name = StoreDescriptor::NameRegister();
|
||||
Register value = StoreDescriptor::ValueRegister();
|
||||
RegList regs = receiver.bit() | name.bit() | value.bit();
|
||||
if (FLAG_vector_stores) {
|
||||
regs |= VectorStoreICDescriptor::SlotRegister().bit();
|
||||
}
|
||||
Generate_DebugBreakCallHelper(masm, regs, 0);
|
||||
}
|
||||
|
||||
|
||||
void DebugCodegen::GenerateKeyedLoadICDebugBreak(MacroAssembler* masm) {
|
||||
// Calling convention for keyed IC load (from ic-mips64.cc).
|
||||
GenerateLoadICDebugBreak(masm);
|
||||
}
|
||||
|
||||
|
||||
void DebugCodegen::GenerateKeyedStoreICDebugBreak(MacroAssembler* masm) {
|
||||
// Calling convention for IC keyed store call (from ic-mips64.cc).
|
||||
GenerateStoreICDebugBreak(masm);
|
||||
}
|
||||
|
||||
|
||||
void DebugCodegen::GenerateCompareNilICDebugBreak(MacroAssembler* masm) {
|
||||
// Register state for CompareNil IC
|
||||
// ----------- S t a t e -------------
|
||||
// -- a0 : value
|
||||
// -----------------------------------
|
||||
Generate_DebugBreakCallHelper(masm, a0.bit(), 0);
|
||||
}
|
||||
|
||||
|
||||
void DebugCodegen::GenerateReturnDebugBreak(MacroAssembler* masm) {
|
||||
// In places other than IC call sites it is expected that v0 is TOS which
|
||||
// is an object - this is not generally the case so this should be used with
|
||||
|
@ -495,6 +495,7 @@ void FullCodeGenerator::EmitReturnSequence() {
|
||||
Label check_exit_codesize;
|
||||
masm_->bind(&check_exit_codesize);
|
||||
#endif
|
||||
|
||||
// Make sure that the constant pool is not emitted inside of the return
|
||||
// sequence.
|
||||
{ Assembler::BlockTrampolinePoolScope block_trampoline_pool(masm_);
|
||||
@ -502,7 +503,7 @@ void FullCodeGenerator::EmitReturnSequence() {
|
||||
// tool from instrumenting as we rely on the code size here.
|
||||
int32_t arg_count = info_->scope()->num_parameters() + 1;
|
||||
int32_t sp_delta = arg_count * kPointerSize;
|
||||
CodeGenerator::RecordPositions(masm_, function()->end_position() - 1);
|
||||
SetReturnPosition(function());
|
||||
__ RecordJSReturn();
|
||||
masm_->mov(sp, fp);
|
||||
int no_frame_start = masm_->pc_offset();
|
||||
@ -1078,7 +1079,7 @@ void FullCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) {
|
||||
}
|
||||
|
||||
// Record position before stub call for type feedback.
|
||||
SetSourcePosition(clause->position());
|
||||
SetExpressionPosition(clause);
|
||||
Handle<Code> ic = CodeFactory::CompareIC(isolate(), Token::EQ_STRICT,
|
||||
strength(language_mode())).code();
|
||||
CallIC(ic, clause->CompareId());
|
||||
@ -1124,8 +1125,9 @@ void FullCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) {
|
||||
|
||||
void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
|
||||
Comment cmnt(masm_, "[ ForInStatement");
|
||||
SetStatementPosition(stmt, SKIP_BREAK);
|
||||
|
||||
FeedbackVectorSlot slot = stmt->ForInFeedbackSlot();
|
||||
SetStatementPosition(stmt);
|
||||
|
||||
Label loop, exit;
|
||||
ForIn loop_statement(this, stmt);
|
||||
@ -1133,7 +1135,7 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
|
||||
|
||||
// Get the object to enumerate over. If the object is null or undefined, skip
|
||||
// over the loop. See ECMA-262 version 5, section 12.6.4.
|
||||
SetExpressionPosition(stmt->enumerable());
|
||||
SetExpressionAsStatementPosition(stmt->enumerable());
|
||||
VisitForAccumulatorValue(stmt->enumerable());
|
||||
__ mov(a0, result_register()); // Result as param to InvokeBuiltin below.
|
||||
__ LoadRoot(at, Heap::kUndefinedValueRootIndex);
|
||||
@ -1233,7 +1235,7 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
|
||||
// Generate code for doing the condition check.
|
||||
PrepareForBailoutForId(stmt->BodyId(), NO_REGISTERS);
|
||||
__ bind(&loop);
|
||||
SetExpressionPosition(stmt->each());
|
||||
SetExpressionAsStatementPosition(stmt->each());
|
||||
|
||||
// Load the current count to a0, load the length to a1.
|
||||
__ ld(a0, MemOperand(sp, 0 * kPointerSize));
|
||||
@ -1479,7 +1481,7 @@ void FullCodeGenerator::EmitDynamicLookupFastCase(VariableProxy* proxy,
|
||||
|
||||
void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy) {
|
||||
// Record position before possible IC call.
|
||||
SetSourcePosition(proxy->position());
|
||||
SetExpressionPosition(proxy);
|
||||
PrepareForBailoutForId(proxy->BeforeId(), NO_REGISTERS);
|
||||
Variable* var = proxy->var();
|
||||
|
||||
@ -1978,6 +1980,7 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) {
|
||||
DCHECK(expr->target()->IsValidReferenceExpression());
|
||||
|
||||
Comment cmnt(masm_, "[ Assignment");
|
||||
SetExpressionPosition(expr, INSERT_BREAK);
|
||||
|
||||
Property* property = expr->target()->AsProperty();
|
||||
LhsKind assign_type = Property::GetAssignType(property);
|
||||
@ -2071,7 +2074,6 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) {
|
||||
__ push(v0); // Left operand goes on the stack.
|
||||
VisitForAccumulatorValue(expr->value());
|
||||
|
||||
SetSourcePosition(expr->position() + 1);
|
||||
AccumulatorValueContext context(this);
|
||||
if (ShouldInlineSmiCase(op)) {
|
||||
EmitInlineSmiBinaryOp(expr->binary_operation(),
|
||||
@ -2088,8 +2090,7 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) {
|
||||
VisitForAccumulatorValue(expr->value());
|
||||
}
|
||||
|
||||
// Record source position before possible IC call.
|
||||
SetSourcePosition(expr->position());
|
||||
SetExpressionPosition(expr);
|
||||
|
||||
// Store the value.
|
||||
switch (assign_type) {
|
||||
@ -2119,6 +2120,8 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) {
|
||||
|
||||
void FullCodeGenerator::VisitYield(Yield* expr) {
|
||||
Comment cmnt(masm_, "[ Yield");
|
||||
SetExpressionPosition(expr);
|
||||
|
||||
// Evaluate yielded value first; the initial iterator definition depends on
|
||||
// this. It stays on the stack while we update the iterator.
|
||||
VisitForStackValue(expr->expression());
|
||||
@ -2406,7 +2409,7 @@ void FullCodeGenerator::EmitCreateIteratorResult(bool done) {
|
||||
|
||||
|
||||
void FullCodeGenerator::EmitNamedPropertyLoad(Property* prop) {
|
||||
SetSourcePosition(prop->position());
|
||||
SetExpressionPosition(prop);
|
||||
Literal* key = prop->key()->AsLiteral();
|
||||
DCHECK(!prop->IsSuperAccess());
|
||||
|
||||
@ -2419,7 +2422,8 @@ void FullCodeGenerator::EmitNamedPropertyLoad(Property* prop) {
|
||||
|
||||
void FullCodeGenerator::EmitNamedSuperPropertyLoad(Property* prop) {
|
||||
// Stack: receiver, home_object.
|
||||
SetSourcePosition(prop->position());
|
||||
SetExpressionPosition(prop);
|
||||
|
||||
Literal* key = prop->key()->AsLiteral();
|
||||
DCHECK(!key->value()->IsSmi());
|
||||
DCHECK(prop->IsSuperAccess());
|
||||
@ -2431,8 +2435,9 @@ void FullCodeGenerator::EmitNamedSuperPropertyLoad(Property* prop) {
|
||||
|
||||
|
||||
void FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) {
|
||||
SetSourcePosition(prop->position());
|
||||
// Call keyed load IC. It has register arguments receiver and key.
|
||||
SetExpressionPosition(prop);
|
||||
|
||||
Handle<Code> ic = CodeFactory::KeyedLoadIC(isolate(), language_mode()).code();
|
||||
__ li(LoadDescriptor::SlotRegister(),
|
||||
Operand(SmiFromSlot(prop->PropertyFeedbackSlot())));
|
||||
@ -2442,9 +2447,8 @@ void FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) {
|
||||
|
||||
void FullCodeGenerator::EmitKeyedSuperPropertyLoad(Property* prop) {
|
||||
// Stack: receiver, home_object, key.
|
||||
SetExpressionPosition(prop);
|
||||
__ Push(Smi::FromInt(language_mode()));
|
||||
SetSourcePosition(prop->position());
|
||||
|
||||
__ CallRuntime(Runtime::kLoadKeyedFromSuper, 4);
|
||||
}
|
||||
|
||||
@ -2818,8 +2822,6 @@ void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) {
|
||||
DCHECK(prop != NULL);
|
||||
DCHECK(prop->key()->IsLiteral());
|
||||
|
||||
// Record source code position before IC call.
|
||||
SetSourcePosition(expr->position());
|
||||
__ mov(StoreDescriptor::ValueRegister(), result_register());
|
||||
__ li(StoreDescriptor::NameRegister(),
|
||||
Operand(prop->key()->AsLiteral()->value()));
|
||||
@ -2868,9 +2870,6 @@ void FullCodeGenerator::EmitKeyedSuperPropertyStore(Property* prop) {
|
||||
|
||||
void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) {
|
||||
// Assignment to a property, using a keyed store IC.
|
||||
|
||||
// Record source code position before IC call.
|
||||
SetSourcePosition(expr->position());
|
||||
// Call keyed store IC.
|
||||
// The arguments are:
|
||||
// - a0 is the value,
|
||||
@ -2896,6 +2895,8 @@ void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) {
|
||||
|
||||
void FullCodeGenerator::VisitProperty(Property* expr) {
|
||||
Comment cmnt(masm_, "[ Property");
|
||||
SetExpressionPosition(expr);
|
||||
|
||||
Expression* key = expr->key();
|
||||
|
||||
if (key->IsPropertyName()) {
|
||||
@ -2971,12 +2972,12 @@ void FullCodeGenerator::EmitCallWithLoadIC(Call* expr) {
|
||||
|
||||
|
||||
void FullCodeGenerator::EmitSuperCallWithLoadIC(Call* expr) {
|
||||
SetExpressionPosition(expr);
|
||||
Expression* callee = expr->expression();
|
||||
DCHECK(callee->IsProperty());
|
||||
Property* prop = callee->AsProperty();
|
||||
DCHECK(prop->IsSuperAccess());
|
||||
|
||||
SetSourcePosition(prop->position());
|
||||
Literal* key = prop->key()->AsLiteral();
|
||||
DCHECK(!key->value()->IsSmi());
|
||||
// Load the function from the receiver.
|
||||
@ -3038,7 +3039,7 @@ void FullCodeGenerator::EmitKeyedSuperCallWithLoadIC(Call* expr) {
|
||||
Property* prop = callee->AsProperty();
|
||||
DCHECK(prop->IsSuperAccess());
|
||||
|
||||
SetSourcePosition(prop->position());
|
||||
SetExpressionPosition(prop);
|
||||
// Load the function from the receiver.
|
||||
const Register scratch = a1;
|
||||
SuperPropertyReference* super_ref = prop->obj()->AsSuperPropertyReference();
|
||||
@ -3072,14 +3073,12 @@ void FullCodeGenerator::EmitCall(Call* expr, CallICState::CallType call_type) {
|
||||
// Load the arguments.
|
||||
ZoneList<Expression*>* args = expr->arguments();
|
||||
int arg_count = args->length();
|
||||
{ PreservePositionScope scope(masm()->positions_recorder());
|
||||
for (int i = 0; i < arg_count; i++) {
|
||||
VisitForStackValue(args->at(i));
|
||||
}
|
||||
for (int i = 0; i < arg_count; i++) {
|
||||
VisitForStackValue(args->at(i));
|
||||
}
|
||||
|
||||
// Record source position of the IC call.
|
||||
SetSourcePosition(expr->position());
|
||||
SetExpressionPosition(expr);
|
||||
Handle<Code> ic = CodeFactory::CallIC(isolate(), arg_count, call_type).code();
|
||||
__ li(a3, Operand(SmiFromSlot(expr->CallFeedbackICSlot())));
|
||||
__ ld(a1, MemOperand(sp, (arg_count + 1) * kPointerSize));
|
||||
@ -3137,13 +3136,11 @@ void FullCodeGenerator::PushCalleeAndWithBaseObject(Call* expr) {
|
||||
VariableProxy* callee = expr->expression()->AsVariableProxy();
|
||||
if (callee->var()->IsLookupSlot()) {
|
||||
Label slow, done;
|
||||
SetSourcePosition(callee->position());
|
||||
{
|
||||
PreservePositionScope scope(masm()->positions_recorder());
|
||||
// Generate code for loading from variables potentially shadowed
|
||||
// by eval-introduced variables.
|
||||
EmitDynamicLookupFastCase(callee, NOT_INSIDE_TYPEOF, &slow, &done);
|
||||
}
|
||||
|
||||
SetExpressionPosition(callee);
|
||||
// Generate code for loading from variables potentially shadowed by
|
||||
// eval-introduced variables.
|
||||
EmitDynamicLookupFastCase(callee, NOT_INSIDE_TYPEOF, &slow, &done);
|
||||
|
||||
__ bind(&slow);
|
||||
// Call the runtime to find the function to call (returned in v0)
|
||||
@ -3196,8 +3193,6 @@ void FullCodeGenerator::VisitCall(Call* expr) {
|
||||
// function using the given arguments.
|
||||
ZoneList<Expression*>* args = expr->arguments();
|
||||
int arg_count = args->length();
|
||||
|
||||
{ PreservePositionScope pos_scope(masm()->positions_recorder());
|
||||
PushCalleeAndWithBaseObject(expr);
|
||||
|
||||
// Push the arguments.
|
||||
@ -3215,9 +3210,8 @@ void FullCodeGenerator::VisitCall(Call* expr) {
|
||||
__ sd(v0, MemOperand(sp, (arg_count + 1) * kPointerSize));
|
||||
|
||||
PrepareForBailoutForId(expr->EvalId(), NO_REGISTERS);
|
||||
}
|
||||
// Record source position for debugger.
|
||||
SetSourcePosition(expr->position());
|
||||
SetExpressionPosition(expr);
|
||||
CallFunctionStub stub(isolate(), arg_count, NO_CALL_FUNCTION_FLAGS);
|
||||
__ ld(a1, MemOperand(sp, (arg_count + 1) * kPointerSize));
|
||||
__ CallStub(&stub);
|
||||
@ -3241,10 +3235,7 @@ void FullCodeGenerator::VisitCall(Call* expr) {
|
||||
EmitKeyedSuperCallWithLoadIC(expr);
|
||||
}
|
||||
} else {
|
||||
{
|
||||
PreservePositionScope scope(masm()->positions_recorder());
|
||||
VisitForStackValue(property->obj());
|
||||
}
|
||||
if (is_named_call) {
|
||||
EmitCallWithLoadIC(expr);
|
||||
} else {
|
||||
@ -3256,9 +3247,7 @@ void FullCodeGenerator::VisitCall(Call* expr) {
|
||||
} else {
|
||||
DCHECK(call_type == Call::OTHER_CALL);
|
||||
// Call to an arbitrary expression not handled specially above.
|
||||
{ PreservePositionScope scope(masm()->positions_recorder());
|
||||
VisitForStackValue(callee);
|
||||
}
|
||||
__ LoadRoot(a1, Heap::kUndefinedValueRootIndex);
|
||||
__ push(a1);
|
||||
// Emit function call.
|
||||
@ -3293,7 +3282,7 @@ void FullCodeGenerator::VisitCallNew(CallNew* expr) {
|
||||
|
||||
// Call the construct call builtin that handles allocation and
|
||||
// constructor invocation.
|
||||
SetSourcePosition(expr->position());
|
||||
SetExpressionPosition(expr);
|
||||
|
||||
// Load function and argument count into a1 and a0.
|
||||
__ li(a0, Operand(arg_count));
|
||||
@ -3336,7 +3325,7 @@ void FullCodeGenerator::EmitSuperConstructorCall(Call* expr) {
|
||||
|
||||
// Call the construct call builtin that handles allocation and
|
||||
// constructor invocation.
|
||||
SetSourcePosition(expr->position());
|
||||
SetExpressionPosition(expr);
|
||||
|
||||
// Load function and argument count into a1 and a0.
|
||||
__ li(a0, Operand(arg_count));
|
||||
@ -4752,8 +4741,7 @@ void FullCodeGenerator::EmitCallJSRuntimeFunction(CallRuntime* expr) {
|
||||
ZoneList<Expression*>* args = expr->arguments();
|
||||
int arg_count = args->length();
|
||||
|
||||
// Record source position of the IC call.
|
||||
SetSourcePosition(expr->position());
|
||||
SetExpressionPosition(expr);
|
||||
CallFunctionStub stub(isolate(), arg_count, NO_CALL_FUNCTION_FLAGS);
|
||||
__ ld(a1, MemOperand(sp, (arg_count + 1) * kPointerSize));
|
||||
__ CallStub(&stub);
|
||||
@ -4930,7 +4918,6 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
|
||||
DCHECK(expr->expression()->IsValidReferenceExpression());
|
||||
|
||||
Comment cmnt(masm_, "[ CountOperation");
|
||||
SetSourcePosition(expr->position());
|
||||
|
||||
Property* prop = expr->expression()->AsProperty();
|
||||
LhsKind assign_type = Property::GetAssignType(prop);
|
||||
@ -5087,8 +5074,8 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
|
||||
__ mov(a1, v0);
|
||||
__ li(a0, Operand(Smi::FromInt(count_value)));
|
||||
|
||||
// Record position before stub call.
|
||||
SetSourcePosition(expr->position());
|
||||
SetExpressionPosition(expr);
|
||||
|
||||
|
||||
Handle<Code> code = CodeFactory::BinaryOpIC(isolate(), Token::ADD,
|
||||
strength(language_mode())).code();
|
||||
@ -5304,7 +5291,7 @@ void FullCodeGenerator::EmitLiteralCompareTypeof(Expression* expr,
|
||||
|
||||
void FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) {
|
||||
Comment cmnt(masm_, "[ CompareOperation");
|
||||
SetSourcePosition(expr->position());
|
||||
SetExpressionPosition(expr);
|
||||
|
||||
// First we try a fast inlined version of the compare when one of
|
||||
// the operands is a literal.
|
||||
@ -5355,8 +5342,7 @@ void FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) {
|
||||
Split(cc, a1, Operand(a0), if_true, if_false, NULL);
|
||||
__ bind(&slow_case);
|
||||
}
|
||||
// Record position and call the compare IC.
|
||||
SetSourcePosition(expr->position());
|
||||
|
||||
Handle<Code> ic = CodeFactory::CompareIC(
|
||||
isolate(), op, strength(language_mode())).code();
|
||||
CallIC(ic, expr->CompareOperationFeedbackId());
|
||||
|
@ -3208,7 +3208,7 @@ void Parser::InitializeForEachStatement(ForEachStatement* stmt,
|
||||
Expression* result_value = factory()->NewProperty(
|
||||
result_proxy, value_literal, RelocInfo::kNoPosition);
|
||||
assign_each = factory()->NewAssignment(Token::ASSIGN, each, result_value,
|
||||
each->position());
|
||||
RelocInfo::kNoPosition);
|
||||
}
|
||||
|
||||
for_of->Initialize(each, subject, body,
|
||||
@ -3592,6 +3592,7 @@ Statement* Parser::ParseForStatement(ZoneList<const AstRawString*>* labels,
|
||||
parsing_result.declarations[0];
|
||||
auto descriptor = parsing_result.descriptor;
|
||||
descriptor.declaration_pos = RelocInfo::kNoPosition;
|
||||
descriptor.initialization_pos = RelocInfo::kNoPosition;
|
||||
decl.initializer = factory()->NewVariableProxy(temp);
|
||||
|
||||
PatternRewriter::DeclareAndInitializeVariables(
|
||||
@ -3688,7 +3689,8 @@ Statement* Parser::ParseForStatement(ZoneList<const AstRawString*>* labels,
|
||||
return loop;
|
||||
|
||||
} else {
|
||||
init = factory()->NewExpressionStatement(expression, position());
|
||||
init =
|
||||
factory()->NewExpressionStatement(expression, lhs_location.beg_pos);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -159,50 +159,6 @@ void DebugCodegen::GenerateCallICStubDebugBreak(MacroAssembler* masm) {
|
||||
}
|
||||
|
||||
|
||||
void DebugCodegen::GenerateLoadICDebugBreak(MacroAssembler* masm) {
|
||||
// Register state for IC load call (from ic-x64.cc).
|
||||
Register receiver = LoadDescriptor::ReceiverRegister();
|
||||
Register name = LoadDescriptor::NameRegister();
|
||||
Register slot = LoadDescriptor::SlotRegister();
|
||||
RegList regs = receiver.bit() | name.bit() | slot.bit();
|
||||
Generate_DebugBreakCallHelper(masm, regs, 0, false);
|
||||
}
|
||||
|
||||
|
||||
void DebugCodegen::GenerateStoreICDebugBreak(MacroAssembler* masm) {
|
||||
// Register state for IC store call (from ic-x64.cc).
|
||||
Register receiver = StoreDescriptor::ReceiverRegister();
|
||||
Register name = StoreDescriptor::NameRegister();
|
||||
Register value = StoreDescriptor::ValueRegister();
|
||||
RegList regs = receiver.bit() | name.bit() | value.bit();
|
||||
if (FLAG_vector_stores) {
|
||||
regs |= VectorStoreICDescriptor::SlotRegister().bit();
|
||||
}
|
||||
Generate_DebugBreakCallHelper(masm, regs, 0, false);
|
||||
}
|
||||
|
||||
|
||||
void DebugCodegen::GenerateKeyedLoadICDebugBreak(MacroAssembler* masm) {
|
||||
// Register state for keyed IC load call (from ic-x64.cc).
|
||||
GenerateLoadICDebugBreak(masm);
|
||||
}
|
||||
|
||||
|
||||
void DebugCodegen::GenerateKeyedStoreICDebugBreak(MacroAssembler* masm) {
|
||||
// Register state for keyed IC store call (from ic-x64.cc).
|
||||
GenerateStoreICDebugBreak(masm);
|
||||
}
|
||||
|
||||
|
||||
void DebugCodegen::GenerateCompareNilICDebugBreak(MacroAssembler* masm) {
|
||||
// Register state for CompareNil IC
|
||||
// ----------- S t a t e -------------
|
||||
// -- rax : value
|
||||
// -----------------------------------
|
||||
Generate_DebugBreakCallHelper(masm, rax.bit(), 0, false);
|
||||
}
|
||||
|
||||
|
||||
void DebugCodegen::GenerateReturnDebugBreak(MacroAssembler* masm) {
|
||||
// Register state just before return from JS function (from codegen-x64.cc).
|
||||
// ----------- S t a t e -------------
|
||||
|
@ -472,7 +472,7 @@ void FullCodeGenerator::EmitReturnSequence() {
|
||||
Label check_exit_codesize;
|
||||
masm_->bind(&check_exit_codesize);
|
||||
#endif
|
||||
CodeGenerator::RecordPositions(masm_, function()->end_position() - 1);
|
||||
SetReturnPosition(function());
|
||||
__ RecordJSReturn();
|
||||
// Do not use the leave instruction here because it is too short to
|
||||
// patch with the code required by the debugger.
|
||||
@ -1046,7 +1046,7 @@ void FullCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) {
|
||||
}
|
||||
|
||||
// Record position before stub call for type feedback.
|
||||
SetSourcePosition(clause->position());
|
||||
SetExpressionPosition(clause);
|
||||
Handle<Code> ic = CodeFactory::CompareIC(isolate(), Token::EQ_STRICT,
|
||||
strength(language_mode())).code();
|
||||
CallIC(ic, clause->CompareId());
|
||||
@ -1093,8 +1093,9 @@ void FullCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) {
|
||||
|
||||
void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
|
||||
Comment cmnt(masm_, "[ ForInStatement");
|
||||
SetStatementPosition(stmt, SKIP_BREAK);
|
||||
|
||||
FeedbackVectorSlot slot = stmt->ForInFeedbackSlot();
|
||||
SetStatementPosition(stmt);
|
||||
|
||||
Label loop, exit;
|
||||
ForIn loop_statement(this, stmt);
|
||||
@ -1102,7 +1103,7 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
|
||||
|
||||
// Get the object to enumerate over. If the object is null or undefined, skip
|
||||
// over the loop. See ECMA-262 version 5, section 12.6.4.
|
||||
SetExpressionPosition(stmt->enumerable());
|
||||
SetExpressionAsStatementPosition(stmt->enumerable());
|
||||
VisitForAccumulatorValue(stmt->enumerable());
|
||||
__ CompareRoot(rax, Heap::kUndefinedValueRootIndex);
|
||||
__ j(equal, &exit);
|
||||
@ -1206,7 +1207,7 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
|
||||
// Generate code for doing the condition check.
|
||||
PrepareForBailoutForId(stmt->BodyId(), NO_REGISTERS);
|
||||
__ bind(&loop);
|
||||
SetExpressionPosition(stmt->each());
|
||||
SetExpressionAsStatementPosition(stmt->each());
|
||||
|
||||
__ movp(rax, Operand(rsp, 0 * kPointerSize)); // Get the current index.
|
||||
__ cmpp(rax, Operand(rsp, 1 * kPointerSize)); // Compare to the array length.
|
||||
@ -1455,7 +1456,7 @@ void FullCodeGenerator::EmitDynamicLookupFastCase(VariableProxy* proxy,
|
||||
|
||||
void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy) {
|
||||
// Record position before possible IC call.
|
||||
SetSourcePosition(proxy->position());
|
||||
SetExpressionPosition(proxy);
|
||||
PrepareForBailoutForId(proxy->BeforeId(), NO_REGISTERS);
|
||||
Variable* var = proxy->var();
|
||||
|
||||
@ -1949,6 +1950,7 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) {
|
||||
DCHECK(expr->target()->IsValidReferenceExpression());
|
||||
|
||||
Comment cmnt(masm_, "[ Assignment");
|
||||
SetExpressionPosition(expr, INSERT_BREAK);
|
||||
|
||||
Property* property = expr->target()->AsProperty();
|
||||
LhsKind assign_type = Property::GetAssignType(property);
|
||||
@ -2037,7 +2039,6 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) {
|
||||
__ Push(rax); // Left operand goes on the stack.
|
||||
VisitForAccumulatorValue(expr->value());
|
||||
|
||||
SetSourcePosition(expr->position() + 1);
|
||||
AccumulatorValueContext context(this);
|
||||
if (ShouldInlineSmiCase(op)) {
|
||||
EmitInlineSmiBinaryOp(expr->binary_operation(),
|
||||
@ -2053,8 +2054,7 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) {
|
||||
VisitForAccumulatorValue(expr->value());
|
||||
}
|
||||
|
||||
// Record source position before possible IC call.
|
||||
SetSourcePosition(expr->position());
|
||||
SetExpressionPosition(expr);
|
||||
|
||||
// Store the value.
|
||||
switch (assign_type) {
|
||||
@ -2084,6 +2084,8 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) {
|
||||
|
||||
void FullCodeGenerator::VisitYield(Yield* expr) {
|
||||
Comment cmnt(masm_, "[ Yield");
|
||||
SetExpressionPosition(expr);
|
||||
|
||||
// Evaluate yielded value first; the initial iterator definition depends on
|
||||
// this. It stays on the stack while we update the iterator.
|
||||
VisitForStackValue(expr->expression());
|
||||
@ -2370,7 +2372,7 @@ void FullCodeGenerator::EmitCreateIteratorResult(bool done) {
|
||||
|
||||
|
||||
void FullCodeGenerator::EmitNamedPropertyLoad(Property* prop) {
|
||||
SetSourcePosition(prop->position());
|
||||
SetExpressionPosition(prop);
|
||||
Literal* key = prop->key()->AsLiteral();
|
||||
DCHECK(!prop->IsSuperAccess());
|
||||
|
||||
@ -2383,7 +2385,7 @@ void FullCodeGenerator::EmitNamedPropertyLoad(Property* prop) {
|
||||
|
||||
void FullCodeGenerator::EmitNamedSuperPropertyLoad(Property* prop) {
|
||||
// Stack: receiver, home_object
|
||||
SetSourcePosition(prop->position());
|
||||
SetExpressionPosition(prop);
|
||||
Literal* key = prop->key()->AsLiteral();
|
||||
DCHECK(!key->value()->IsSmi());
|
||||
DCHECK(prop->IsSuperAccess());
|
||||
@ -2395,7 +2397,7 @@ void FullCodeGenerator::EmitNamedSuperPropertyLoad(Property* prop) {
|
||||
|
||||
|
||||
void FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) {
|
||||
SetSourcePosition(prop->position());
|
||||
SetExpressionPosition(prop);
|
||||
Handle<Code> ic = CodeFactory::KeyedLoadIC(isolate(), language_mode()).code();
|
||||
__ Move(LoadDescriptor::SlotRegister(),
|
||||
SmiFromSlot(prop->PropertyFeedbackSlot()));
|
||||
@ -2405,9 +2407,8 @@ void FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) {
|
||||
|
||||
void FullCodeGenerator::EmitKeyedSuperPropertyLoad(Property* prop) {
|
||||
// Stack: receiver, home_object, key.
|
||||
SetExpressionPosition(prop);
|
||||
__ Push(Smi::FromInt(language_mode()));
|
||||
SetSourcePosition(prop->position());
|
||||
|
||||
__ CallRuntime(Runtime::kLoadKeyedFromSuper, 4);
|
||||
}
|
||||
|
||||
@ -2738,8 +2739,6 @@ void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) {
|
||||
DCHECK(prop != NULL);
|
||||
DCHECK(prop->key()->IsLiteral());
|
||||
|
||||
// Record source code position before IC call.
|
||||
SetSourcePosition(expr->position());
|
||||
__ Move(StoreDescriptor::NameRegister(), prop->key()->AsLiteral()->value());
|
||||
__ Pop(StoreDescriptor::ReceiverRegister());
|
||||
if (FLAG_vector_stores) {
|
||||
@ -2786,12 +2785,9 @@ void FullCodeGenerator::EmitKeyedSuperPropertyStore(Property* prop) {
|
||||
|
||||
void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) {
|
||||
// Assignment to a property, using a keyed store IC.
|
||||
|
||||
__ Pop(StoreDescriptor::NameRegister()); // Key.
|
||||
__ Pop(StoreDescriptor::ReceiverRegister());
|
||||
DCHECK(StoreDescriptor::ValueRegister().is(rax));
|
||||
// Record source code position before IC call.
|
||||
SetSourcePosition(expr->position());
|
||||
Handle<Code> ic =
|
||||
CodeFactory::KeyedStoreIC(isolate(), language_mode()).code();
|
||||
if (FLAG_vector_stores) {
|
||||
@ -2808,6 +2804,8 @@ void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) {
|
||||
|
||||
void FullCodeGenerator::VisitProperty(Property* expr) {
|
||||
Comment cmnt(masm_, "[ Property");
|
||||
SetExpressionPosition(expr);
|
||||
|
||||
Expression* key = expr->key();
|
||||
|
||||
if (key->IsPropertyName()) {
|
||||
@ -2885,8 +2883,8 @@ void FullCodeGenerator::EmitSuperCallWithLoadIC(Call* expr) {
|
||||
DCHECK(callee->IsProperty());
|
||||
Property* prop = callee->AsProperty();
|
||||
DCHECK(prop->IsSuperAccess());
|
||||
SetExpressionPosition(prop);
|
||||
|
||||
SetSourcePosition(prop->position());
|
||||
Literal* key = prop->key()->AsLiteral();
|
||||
DCHECK(!key->value()->IsSmi());
|
||||
// Load the function from the receiver.
|
||||
@ -2947,7 +2945,7 @@ void FullCodeGenerator::EmitKeyedSuperCallWithLoadIC(Call* expr) {
|
||||
Property* prop = callee->AsProperty();
|
||||
DCHECK(prop->IsSuperAccess());
|
||||
|
||||
SetSourcePosition(prop->position());
|
||||
SetExpressionPosition(prop);
|
||||
// Load the function from the receiver.
|
||||
SuperPropertyReference* super_ref = prop->obj()->AsSuperPropertyReference();
|
||||
VisitForStackValue(super_ref->home_object());
|
||||
@ -2981,14 +2979,11 @@ void FullCodeGenerator::EmitCall(Call* expr, CallICState::CallType call_type) {
|
||||
// Load the arguments.
|
||||
ZoneList<Expression*>* args = expr->arguments();
|
||||
int arg_count = args->length();
|
||||
{ PreservePositionScope scope(masm()->positions_recorder());
|
||||
for (int i = 0; i < arg_count; i++) {
|
||||
VisitForStackValue(args->at(i));
|
||||
}
|
||||
for (int i = 0; i < arg_count; i++) {
|
||||
VisitForStackValue(args->at(i));
|
||||
}
|
||||
|
||||
// Record source position of the IC call.
|
||||
SetSourcePosition(expr->position());
|
||||
SetExpressionPosition(expr);
|
||||
Handle<Code> ic = CodeFactory::CallIC(isolate(), arg_count, call_type).code();
|
||||
__ Move(rdx, SmiFromSlot(expr->CallFeedbackICSlot()));
|
||||
__ movp(rdi, Operand(rsp, (arg_count + 1) * kPointerSize));
|
||||
@ -3047,13 +3042,10 @@ void FullCodeGenerator::PushCalleeAndWithBaseObject(Call* expr) {
|
||||
VariableProxy* callee = expr->expression()->AsVariableProxy();
|
||||
if (callee->var()->IsLookupSlot()) {
|
||||
Label slow, done;
|
||||
SetSourcePosition(callee->position());
|
||||
{
|
||||
PreservePositionScope scope(masm()->positions_recorder());
|
||||
// Generate code for loading from variables potentially shadowed by
|
||||
// eval-introduced variables.
|
||||
EmitDynamicLookupFastCase(callee, NOT_INSIDE_TYPEOF, &slow, &done);
|
||||
}
|
||||
SetExpressionPosition(callee);
|
||||
// Generate code for loading from variables potentially shadowed by
|
||||
// eval-introduced variables.
|
||||
EmitDynamicLookupFastCase(callee, NOT_INSIDE_TYPEOF, &slow, &done);
|
||||
__ bind(&slow);
|
||||
// Call the runtime to find the function to call (returned in rax) and
|
||||
// the object holding it (returned in rdx).
|
||||
@ -3103,7 +3095,6 @@ void FullCodeGenerator::VisitCall(Call* expr) {
|
||||
// function using the given arguments.
|
||||
ZoneList<Expression*>* args = expr->arguments();
|
||||
int arg_count = args->length();
|
||||
{ PreservePositionScope pos_scope(masm()->positions_recorder());
|
||||
PushCalleeAndWithBaseObject(expr);
|
||||
|
||||
// Push the arguments.
|
||||
@ -3120,9 +3111,8 @@ void FullCodeGenerator::VisitCall(Call* expr) {
|
||||
__ movp(Operand(rsp, (arg_count + 1) * kPointerSize), rax);
|
||||
|
||||
PrepareForBailoutForId(expr->EvalId(), NO_REGISTERS);
|
||||
}
|
||||
// Record source position for debugger.
|
||||
SetSourcePosition(expr->position());
|
||||
SetExpressionPosition(expr);
|
||||
CallFunctionStub stub(isolate(), arg_count, NO_CALL_FUNCTION_FLAGS);
|
||||
__ movp(rdi, Operand(rsp, (arg_count + 1) * kPointerSize));
|
||||
__ CallStub(&stub);
|
||||
@ -3147,10 +3137,7 @@ void FullCodeGenerator::VisitCall(Call* expr) {
|
||||
EmitKeyedSuperCallWithLoadIC(expr);
|
||||
}
|
||||
} else {
|
||||
{
|
||||
PreservePositionScope scope(masm()->positions_recorder());
|
||||
VisitForStackValue(property->obj());
|
||||
}
|
||||
if (is_named_call) {
|
||||
EmitCallWithLoadIC(expr);
|
||||
} else {
|
||||
@ -3162,9 +3149,7 @@ void FullCodeGenerator::VisitCall(Call* expr) {
|
||||
} else {
|
||||
DCHECK(call_type == Call::OTHER_CALL);
|
||||
// Call to an arbitrary expression not handled specially above.
|
||||
{ PreservePositionScope scope(masm()->positions_recorder());
|
||||
VisitForStackValue(callee);
|
||||
}
|
||||
__ PushRoot(Heap::kUndefinedValueRootIndex);
|
||||
// Emit function call.
|
||||
EmitCall(expr);
|
||||
@ -3198,7 +3183,7 @@ void FullCodeGenerator::VisitCallNew(CallNew* expr) {
|
||||
|
||||
// Call the construct call builtin that handles allocation and
|
||||
// constructor invocation.
|
||||
SetSourcePosition(expr->position());
|
||||
SetExpressionPosition(expr);
|
||||
|
||||
// Load function and argument count into rdi and rax.
|
||||
__ Set(rax, arg_count);
|
||||
@ -3241,7 +3226,7 @@ void FullCodeGenerator::EmitSuperConstructorCall(Call* expr) {
|
||||
|
||||
// Call the construct call builtin that handles allocation and
|
||||
// constructor invocation.
|
||||
SetSourcePosition(expr->position());
|
||||
SetExpressionPosition(expr);
|
||||
|
||||
// Load function and argument count into edi and eax.
|
||||
__ Set(rax, arg_count);
|
||||
@ -4690,8 +4675,7 @@ void FullCodeGenerator::EmitCallJSRuntimeFunction(CallRuntime* expr) {
|
||||
ZoneList<Expression*>* args = expr->arguments();
|
||||
int arg_count = args->length();
|
||||
|
||||
// Record source position of the IC call.
|
||||
SetSourcePosition(expr->position());
|
||||
SetExpressionPosition(expr);
|
||||
CallFunctionStub stub(isolate(), arg_count, NO_CALL_FUNCTION_FLAGS);
|
||||
__ movp(rdi, Operand(rsp, (arg_count + 1) * kPointerSize));
|
||||
__ CallStub(&stub);
|
||||
@ -4872,7 +4856,6 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
|
||||
DCHECK(expr->expression()->IsValidReferenceExpression());
|
||||
|
||||
Comment cmnt(masm_, "[ CountOperation");
|
||||
SetSourcePosition(expr->position());
|
||||
|
||||
Property* prop = expr->expression()->AsProperty();
|
||||
LhsKind assign_type = Property::GetAssignType(prop);
|
||||
@ -5019,8 +5002,7 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
|
||||
}
|
||||
}
|
||||
|
||||
// Record position before stub call.
|
||||
SetSourcePosition(expr->position());
|
||||
SetExpressionPosition(expr);
|
||||
|
||||
// Call stub for +1/-1.
|
||||
__ bind(&stub_call);
|
||||
@ -5240,7 +5222,7 @@ void FullCodeGenerator::EmitLiteralCompareTypeof(Expression* expr,
|
||||
|
||||
void FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) {
|
||||
Comment cmnt(masm_, "[ CompareOperation");
|
||||
SetSourcePosition(expr->position());
|
||||
SetExpressionPosition(expr);
|
||||
|
||||
// First we try a fast inlined version of the compare when one of
|
||||
// the operands is a literal.
|
||||
@ -5294,8 +5276,6 @@ void FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) {
|
||||
__ bind(&slow_case);
|
||||
}
|
||||
|
||||
// Record position and call the compare IC.
|
||||
SetSourcePosition(expr->position());
|
||||
Handle<Code> ic = CodeFactory::CompareIC(
|
||||
isolate(), op, strength(language_mode())).code();
|
||||
CallIC(ic, expr->CompareOperationFeedbackId());
|
||||
|
@ -969,82 +969,6 @@ static void MessageCallbackCount(v8::Handle<v8::Message> message,
|
||||
|
||||
// --- T h e A c t u a l T e s t s
|
||||
|
||||
|
||||
// Test that the debug break function is the expected one for different kinds
|
||||
// of break locations.
|
||||
TEST(DebugStub) {
|
||||
using ::v8::internal::Builtins;
|
||||
using ::v8::internal::Isolate;
|
||||
DebugLocalContext env;
|
||||
v8::HandleScope scope(env->GetIsolate());
|
||||
|
||||
CheckDebugBreakFunction(&env,
|
||||
"function f1(){}", "f1",
|
||||
0,
|
||||
v8::internal::RelocInfo::JS_RETURN,
|
||||
NULL);
|
||||
CheckDebugBreakFunction(&env,
|
||||
"function f2(){x=1;}", "f2",
|
||||
0,
|
||||
v8::internal::RelocInfo::CODE_TARGET,
|
||||
CcTest::i_isolate()->builtins()->builtin(
|
||||
Builtins::kStoreIC_DebugBreak));
|
||||
CheckDebugBreakFunction(
|
||||
&env, "function f3(){x();}", "f3", 0,
|
||||
v8::internal::RelocInfo::CODE_TARGET,
|
||||
CcTest::i_isolate()->builtins()->builtin(Builtins::kLoadIC_DebugBreak));
|
||||
|
||||
// TODO(1240753): Make the test architecture independent or split
|
||||
// parts of the debugger into architecture dependent files. This
|
||||
// part currently disabled as it is not portable between IA32/ARM.
|
||||
// Currently on ICs for keyed store/load on ARM.
|
||||
#if !defined (__arm__) && !defined(__thumb__)
|
||||
CheckDebugBreakFunction(
|
||||
&env,
|
||||
"function f4(){var index='propertyName'; var a={}; a[index] = 'x';}",
|
||||
"f4", 39, v8::internal::RelocInfo::CODE_TARGET,
|
||||
CcTest::i_isolate()->builtins()->builtin(
|
||||
Builtins::kKeyedStoreIC_DebugBreak));
|
||||
CheckDebugBreakFunction(
|
||||
&env,
|
||||
"function f5(){var index='propertyName'; var a={}; return a[index];}",
|
||||
"f5", 39, v8::internal::RelocInfo::CODE_TARGET,
|
||||
CcTest::i_isolate()->builtins()->builtin(
|
||||
Builtins::kKeyedLoadIC_DebugBreak));
|
||||
#endif
|
||||
|
||||
CheckDebugBreakFunction(&env, "function f6(){(0==null)()}", "f6", 0,
|
||||
v8::internal::RelocInfo::CODE_TARGET,
|
||||
CcTest::i_isolate()->builtins()->builtin(
|
||||
Builtins::kCompareNilIC_DebugBreak));
|
||||
|
||||
// Check the debug break code stubs for call ICs with different number of
|
||||
// parameters.
|
||||
// TODO(verwaest): XXX update test.
|
||||
// Handle<Code> debug_break_0 = v8::internal::ComputeCallDebugBreak(0);
|
||||
// Handle<Code> debug_break_1 = v8::internal::ComputeCallDebugBreak(1);
|
||||
// Handle<Code> debug_break_4 = v8::internal::ComputeCallDebugBreak(4);
|
||||
|
||||
// CheckDebugBreakFunction(&env,
|
||||
// "function f4_0(){x();}", "f4_0",
|
||||
// 0,
|
||||
// v8::internal::RelocInfo::CODE_TARGET,
|
||||
// *debug_break_0);
|
||||
|
||||
// CheckDebugBreakFunction(&env,
|
||||
// "function f4_1(){x(1);}", "f4_1",
|
||||
// 0,
|
||||
// v8::internal::RelocInfo::CODE_TARGET,
|
||||
// *debug_break_1);
|
||||
|
||||
// CheckDebugBreakFunction(&env,
|
||||
// "function f4_4(){x(1,2,3,4);}", "f4_4",
|
||||
// 0,
|
||||
// v8::internal::RelocInfo::CODE_TARGET,
|
||||
// *debug_break_4);
|
||||
}
|
||||
|
||||
|
||||
// Test that the debug info in the VM is in sync with the functions being
|
||||
// debugged.
|
||||
TEST(DebugInfo) {
|
||||
@ -2346,7 +2270,7 @@ TEST(DebuggerStatementBreakpoint) {
|
||||
v8::Local<v8::Function> foo = v8::Local<v8::Function>::Cast(
|
||||
env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "foo")));
|
||||
|
||||
// The debugger statement triggers breakpint hit
|
||||
// The debugger statement triggers breakpoint hit
|
||||
foo->Call(env->Global(), 0, NULL);
|
||||
CHECK_EQ(1, break_point_hit_count);
|
||||
|
||||
@ -3270,6 +3194,13 @@ TEST(DebugStepDoWhile) {
|
||||
v8::Local<v8::Function> foo = CompileFunction(&env, src, "foo");
|
||||
SetBreakPoint(foo, 8); // "var a = 0;"
|
||||
|
||||
// Looping 0 times.
|
||||
step_action = StepIn;
|
||||
break_point_hit_count = 0;
|
||||
v8::Handle<v8::Value> argv_0[argc] = {v8::Number::New(isolate, 0)};
|
||||
foo->Call(env->Global(), argc, argv_0);
|
||||
CHECK_EQ(4, break_point_hit_count);
|
||||
|
||||
// Looping 10 times.
|
||||
step_action = StepIn;
|
||||
break_point_hit_count = 0;
|
||||
@ -3312,19 +3243,26 @@ TEST(DebugStepFor) {
|
||||
|
||||
SetBreakPoint(foo, 8); // "a = 1;"
|
||||
|
||||
// Looping 0 times.
|
||||
step_action = StepIn;
|
||||
break_point_hit_count = 0;
|
||||
v8::Handle<v8::Value> argv_0[argc] = {v8::Number::New(isolate, 0)};
|
||||
foo->Call(env->Global(), argc, argv_0);
|
||||
CHECK_EQ(4, break_point_hit_count);
|
||||
|
||||
// Looping 10 times.
|
||||
step_action = StepIn;
|
||||
break_point_hit_count = 0;
|
||||
v8::Handle<v8::Value> argv_10[argc] = { v8::Number::New(isolate, 10) };
|
||||
foo->Call(env->Global(), argc, argv_10);
|
||||
CHECK_EQ(45, break_point_hit_count);
|
||||
CHECK_EQ(34, break_point_hit_count);
|
||||
|
||||
// Looping 100 times.
|
||||
step_action = StepIn;
|
||||
break_point_hit_count = 0;
|
||||
v8::Handle<v8::Value> argv_100[argc] = { v8::Number::New(isolate, 100) };
|
||||
foo->Call(env->Global(), argc, argv_100);
|
||||
CHECK_EQ(405, break_point_hit_count);
|
||||
CHECK_EQ(304, break_point_hit_count);
|
||||
|
||||
// Get rid of the debug event listener.
|
||||
v8::Debug::SetDebugEventListener(NULL);
|
||||
@ -3539,14 +3477,14 @@ TEST(DebugConditional) {
|
||||
step_action = StepIn;
|
||||
break_point_hit_count = 0;
|
||||
foo->Call(env->Global(), 0, NULL);
|
||||
CHECK_EQ(5, break_point_hit_count);
|
||||
CHECK_EQ(4, break_point_hit_count);
|
||||
|
||||
step_action = StepIn;
|
||||
break_point_hit_count = 0;
|
||||
const int argc = 1;
|
||||
v8::Handle<v8::Value> argv_true[argc] = { v8::True(isolate) };
|
||||
foo->Call(env->Global(), argc, argv_true);
|
||||
CHECK_EQ(5, break_point_hit_count);
|
||||
CHECK_EQ(4, break_point_hit_count);
|
||||
|
||||
// Get rid of the debug event listener.
|
||||
v8::Debug::SetDebugEventListener(NULL);
|
||||
|
@ -165,7 +165,7 @@ function listener(event, exec_state, event_data, data) {
|
||||
assertEquals("f", response.lookup(frame.func.ref).name);
|
||||
assertTrue(frame.constructCall);
|
||||
assertEquals(31, frame.line);
|
||||
assertEquals(3, frame.column);
|
||||
assertEquals(2, frame.column);
|
||||
assertEquals(2, frame.arguments.length);
|
||||
assertEquals('x', frame.arguments[0].name);
|
||||
assertEquals('number', response.lookup(frame.arguments[0].value.ref).type);
|
||||
@ -179,7 +179,7 @@ function listener(event, exec_state, event_data, data) {
|
||||
assertEquals(0, frame.index);
|
||||
assertEquals("f", response.lookup(frame.func.ref).name);
|
||||
assertEquals(31, frame.line);
|
||||
assertEquals(3, frame.column);
|
||||
assertEquals(2, frame.column);
|
||||
assertEquals(2, frame.arguments.length);
|
||||
assertEquals('x', frame.arguments[0].name);
|
||||
assertEquals('number', response.lookup(frame.arguments[0].value.ref).type);
|
||||
|
@ -211,7 +211,6 @@ assertTrue(Debug.showBreakPoints(g).indexOf("[B0]") < 0);
|
||||
// (This may be sensitive to compiler break position map generation).
|
||||
function h() {a=f(f2(1,2),f3())+f3();b=f3();}
|
||||
var scenario = [
|
||||
[5, "{a[B0]=f"],
|
||||
[6, "{a=[B0]f("],
|
||||
[7, "{a=f([B0]f2("],
|
||||
[16, "f2(1,2),[B0]f3()"],
|
||||
|
@ -11,7 +11,7 @@ function f0() {
|
||||
try {
|
||||
throw 1;
|
||||
} catch (e) {
|
||||
try{
|
||||
try {
|
||||
f1();
|
||||
} catch (e) {
|
||||
var v02 = 2; // Break 13
|
||||
@ -19,6 +19,8 @@ function f0() {
|
||||
}
|
||||
var v03 = 3;
|
||||
var v04 = 4;
|
||||
eval('var v05 = 5; // Break 14');
|
||||
var v06 = 6; // Break 15
|
||||
}
|
||||
|
||||
function f1() {
|
||||
@ -104,7 +106,7 @@ for (step_size = 1; step_size < 6; step_size++) {
|
||||
Debug.setListener(listener);
|
||||
debugger; // Break 0
|
||||
f0();
|
||||
Debug.setListener(null); // Break 14
|
||||
Debug.setListener(null); // Break 16
|
||||
assertTrue(break_count > 14);
|
||||
}
|
||||
|
||||
|
@ -14,6 +14,7 @@ function listener(event, execState, eventData, data) {
|
||||
if (!done) {
|
||||
execState.prepareStep(Debug.StepAction.StepInto);
|
||||
var s = execState.frame().sourceLineText();
|
||||
print(s);
|
||||
assertTrue(s.indexOf('// ' + stepCount + '.') !== -1);
|
||||
stepCount++;
|
||||
}
|
||||
@ -24,10 +25,10 @@ Debug.setListener(listener);
|
||||
|
||||
|
||||
class Base {
|
||||
constructor() {
|
||||
var x = 1; // 1.
|
||||
var y = 2; // 2.
|
||||
done = true; // 3.
|
||||
constructor() { // 1.
|
||||
var x = 1; // 2.
|
||||
var y = 2; // 3.
|
||||
done = true; // 4.
|
||||
}
|
||||
}
|
||||
|
||||
@ -40,7 +41,7 @@ class Derived extends Base {}
|
||||
var bp = Debug.setBreakPoint(Base, 0);
|
||||
|
||||
new Base();
|
||||
assertEquals(4, stepCount);
|
||||
assertEquals(5, stepCount);
|
||||
|
||||
Debug.clearBreakPoint(bp);
|
||||
})();
|
||||
@ -52,7 +53,7 @@ class Derived extends Base {}
|
||||
|
||||
var bp = Debug.setBreakPoint(Base, 0);
|
||||
new Derived();
|
||||
assertEquals(4, stepCount);
|
||||
assertEquals(5, stepCount);
|
||||
|
||||
Debug.clearBreakPoint(bp);
|
||||
})();
|
||||
@ -68,7 +69,7 @@ class Derived extends Base {}
|
||||
|
||||
var bp = Debug.setBreakPoint(f, 0);
|
||||
f();
|
||||
assertEquals(4, stepCount);
|
||||
assertEquals(5, stepCount);
|
||||
|
||||
Debug.clearBreakPoint(bp);
|
||||
})();
|
||||
@ -86,7 +87,7 @@ class Derived extends Base {}
|
||||
|
||||
var bp = Debug.setBreakPoint(f, 0);
|
||||
f();
|
||||
assertEquals(4, stepCount);
|
||||
assertEquals(5, stepCount);
|
||||
|
||||
Debug.clearBreakPoint(bp);
|
||||
})();
|
||||
@ -104,7 +105,7 @@ class Derived extends Base {}
|
||||
|
||||
var bp = Debug.setBreakPoint(f, 0);
|
||||
f();
|
||||
assertEquals(4, stepCount);
|
||||
assertEquals(5, stepCount);
|
||||
|
||||
Debug.clearBreakPoint(bp);
|
||||
})();
|
||||
|
@ -106,7 +106,7 @@ var expected = [
|
||||
// For-var: var decl, condition, body, next, condition, body, ...
|
||||
"k7","k20","K4","k23","k20","K4","k23","k20","K4","k23","k20",
|
||||
// For: init, condition, body, next, condition, body, ...
|
||||
"l11","l16","L4","l19","l16","L4","l19","l16","L4","l19","l16",
|
||||
"l7","l16","L4","l19","l16","L4","l19","l16","L4","l19","l16",
|
||||
// Exit.
|
||||
"y0","z0",
|
||||
]
|
||||
|
@ -354,9 +354,6 @@
|
||||
'regress/regress-2185-2': [PASS, TIMEOUT],
|
||||
'whitespaces': [PASS, TIMEOUT, SLOW],
|
||||
|
||||
# BUG(v8:3147). It works on other architectures by accident.
|
||||
'regress/regress-conditional-position': [FAIL],
|
||||
|
||||
# BUG(v8:3457).
|
||||
'deserialize-reference': [PASS, FAIL],
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user