}
-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
{ 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();
}
// 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());
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);
// 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);
// 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));
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();
DCHECK(expr->target()->IsValidReferenceExpression());
Comment cmnt(masm_, "[ Assignment");
+ SetExpressionPosition(expr, INSERT_BREAK);
Property* property = expr->target()->AsProperty();
LhsKind assign_type = Property::GetAssignType(property);
__ 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(),
VisitForAccumulatorValue(expr->value());
}
- // Record source position before possible IC call.
- SetSourcePosition(expr->position());
+ SetExpressionPosition(expr);
// Store the value.
switch (assign_type) {
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());
void FullCodeGenerator::EmitNamedPropertyLoad(Property* prop) {
- SetSourcePosition(prop->position());
+ SetExpressionPosition(prop);
Literal* key = prop->key()->AsLiteral();
DCHECK(!prop->IsSuperAccess());
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());
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())));
void FullCodeGenerator::EmitKeyedSuperPropertyLoad(Property* prop) {
// Stack: receiver, home_object, key.
+ SetExpressionPosition(prop);
__ Push(Smi::FromInt(language_mode()));
- SetSourcePosition(prop->position());
-
__ CallRuntime(Runtime::kLoadKeyedFromSuper, 4);
}
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());
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));
void FullCodeGenerator::VisitProperty(Property* expr) {
Comment cmnt(masm_, "[ Property");
+ SetExpressionPosition(expr);
+
Expression* key = expr->key();
if (key->IsPropertyName()) {
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.
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();
// 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));
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)
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 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);
+ // 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));
+ // Touch up the stack with the resolved function.
+ __ str(r0, MemOperand(sp, (arg_count + 1) * kPointerSize));
- PrepareForBailoutForId(expr->EvalId(), NO_REGISTERS);
- }
+ 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);
EmitKeyedSuperCallWithLoadIC(expr);
}
} else {
- {
- PreservePositionScope scope(masm()->positions_recorder());
VisitForStackValue(property->obj());
- }
if (is_named_call) {
EmitCallWithLoadIC(expr);
} else {
} 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.
// 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));
// 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));
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);
DCHECK(expr->expression()->IsValidReferenceExpression());
Comment cmnt(masm_, "[ CountOperation");
- SetSourcePosition(expr->position());
Property* prop = expr->expression()->AsProperty();
LhsKind assign_type = Property::GetAssignType(prop);
__ 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();
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.
__ 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());
}
-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
{
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
}
// 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());
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);
// 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;
// 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);
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();
DCHECK(expr->target()->IsValidReferenceExpression());
Comment cmnt(masm_, "[ Assignment");
+ SetExpressionPosition(expr, INSERT_BREAK);
Property* property = expr->target()->AsProperty();
LhsKind assign_type = Property::GetAssignType(property);
__ 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(),
VisitForAccumulatorValue(expr->value());
}
- // Record source position before possible IC call.
- SetSourcePosition(expr->position());
+ SetExpressionPosition(expr);
// Store the value.
switch (assign_type) {
void FullCodeGenerator::EmitNamedPropertyLoad(Property* prop) {
- SetSourcePosition(prop->position());
+ SetExpressionPosition(prop);
Literal* key = prop->key()->AsLiteral();
DCHECK(!prop->IsSuperAccess());
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());
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(),
void FullCodeGenerator::EmitKeyedSuperPropertyLoad(Property* prop) {
// Stack: receiver, home_object, key.
+ SetExpressionPosition(prop);
__ Push(Smi::FromInt(language_mode()));
- SetSourcePosition(prop->position());
-
__ CallRuntime(Runtime::kLoadKeyedFromSuper, 4);
}
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());
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));
void FullCodeGenerator::VisitProperty(Property* expr) {
Comment cmnt(masm_, "[ Property");
+ SetExpressionPosition(expr);
Expression* key = expr->key();
if (key->IsPropertyName()) {
DCHECK(callee->IsProperty());
Property* prop = callee->AsProperty();
DCHECK(prop->IsSuperAccess());
+ SetExpressionPosition(prop);
- SetSourcePosition(prop->position());
Literal* key = prop->key()->AsLiteral();
DCHECK(!key->value()->IsSmi());
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;
// 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()));
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)
ZoneList<Expression*>* args = expr->arguments();
int arg_count = args->length();
- {
- PreservePositionScope pos_scope(masm()->positions_recorder());
PushCalleeAndWithBaseObject(expr);
// Push the arguments.
__ 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);
EmitKeyedSuperCallWithLoadIC(expr);
}
} else {
- {
- PreservePositionScope scope(masm()->positions_recorder());
VisitForStackValue(property->obj());
- }
if (is_named_call) {
EmitCallWithLoadIC(expr);
} else {
} 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.
// 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);
// 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);
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);
DCHECK(expr->expression()->IsValidReferenceExpression());
Comment cmnt(masm_, "[ CountOperation");
- SetSourcePosition(expr->position());
Property* prop = expr->expression()->AsProperty();
LhsKind assign_type = Property::GetAssignType(prop);
__ Mov(x1, x0);
__ Mov(x0, Smi::FromInt(count_value));
- // Record position before stub call.
- SetSourcePosition(expr->position());
+ SetExpressionPosition(expr);
{
Assembler::BlockPoolsScope scope(masm_);
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.
__ 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());
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());
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;
void Assembler::RecordDebugBreakSlot() {
- positions_recorder()->WriteRecordedPositions();
EnsureSpace ensure_space(this);
RecordRelocInfo(RelocInfo::DEBUG_BREAK_SLOT);
}
// 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
}
-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);
}
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, \
#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
// 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);
};
~RelocInfo::ModeMask(RelocInfo::CODE_AGE_SEQUENCE)),
break_index_(-1),
position_(1),
- statement_position_(1),
- has_immediate_position_(false) {
+ statement_position_(1) {
Next();
}
debug_info_->shared()->start_position());
DCHECK(position_ >= 0);
DCHECK(statement_position_ >= 0);
- has_immediate_position_ = true;
continue;
}
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) {
break;
}
}
- has_immediate_position_ = false;
}
// 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()) {
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;
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;
// 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.
-
- // 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 {
+ return;
+ }
+
+ 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) {
}
}
- // 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();
}
int break_index_;
int position_;
int statement_position_;
- bool has_immediate_position_;
DisallowHeapAllocation no_gc_;
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) {
}
+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::VisitSuperPropertyReference(
- SuperPropertyReference* super) {
- __ CallRuntime(Runtime::kThrowUnsupportedSuperError, 0);
+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::VisitSuperCallReference(SuperCallReference* super) {
- __ CallRuntime(Runtime::kThrowUnsupportedSuperError, 0);
+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::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::VisitSuperPropertyReference(
+ SuperPropertyReference* super) {
+ __ CallRuntime(Runtime::kThrowUnsupportedSuperError, 0);
}
-void FullCodeGenerator::SetSourcePosition(int pos) {
- if (pos != RelocInfo::kNoPosition) {
- masm_->positions_recorder()->RecordPosition(pos);
- }
+void FullCodeGenerator::VisitSuperCallReference(SuperCallReference* super) {
+ __ CallRuntime(Runtime::kThrowUnsupportedSuperError, 0);
}
VisitForStackValue(left);
VisitForAccumulatorValue(right);
- SetSourcePosition(expr->position());
+ SetExpressionPosition(expr);
if (ShouldInlineSmiCase(op)) {
EmitInlineSmiBinaryOp(expr, op, left, right);
} else {
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);
// 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(),
__ bind(&loop);
- SetExpressionPosition(stmt->cond());
+ SetExpressionAsStatementPosition(stmt->cond());
VisitForControl(stmt->cond(),
&body,
loop_statement.break_label(),
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());
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(),
void FullCodeGenerator::VisitForOfStatement(ForOfStatement* stmt) {
Comment cmnt(masm_, "[ ForOfStatement");
- SetStatementPosition(stmt);
Iteration loop_statement(this, stmt);
increment_loop_depth();
__ bind(loop_statement.continue_label());
// result = iterator.next()
- SetExpressionPosition(stmt->next_result());
+ SetExpressionAsStatementPosition(stmt->next_result());
VisitForEffect(stmt->next_result());
// if (result.done) break;
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
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.
//
void FullCodeGenerator::VisitThrow(Throw* expr) {
Comment cmnt(masm_, "[ Throw");
VisitForStackValue(expr->exception());
- SetSourcePosition(expr->position());
+ SetExpressionPosition(expr);
__ CallRuntime(Runtime::kThrow, 1);
// Never returns here.
}
// 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.
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);
}
-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 -------------
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);
}
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.
__ 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());
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);
// 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);
// 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.
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();
DCHECK(expr->target()->IsValidReferenceExpression());
Comment cmnt(masm_, "[ Assignment");
+ SetExpressionPosition(expr, INSERT_BREAK);
Property* property = expr->target()->AsProperty();
LhsKind assign_type = Property::GetAssignType(property);
__ push(eax); // Left operand goes on the stack.
VisitForAccumulatorValue(expr->value());
- SetSourcePosition(expr->position() + 1);
if (ShouldInlineSmiCase(op)) {
EmitInlineSmiBinaryOp(expr->binary_operation(),
op,
VisitForAccumulatorValue(expr->value());
}
- // Record source position before possible IC call.
- SetSourcePosition(expr->position());
+ SetExpressionPosition(expr);
// Store the value.
switch (assign_type) {
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());
void FullCodeGenerator::EmitNamedPropertyLoad(Property* prop) {
- SetSourcePosition(prop->position());
+ SetExpressionPosition(prop);
Literal* key = prop->key()->AsLiteral();
DCHECK(!key->value()->IsSmi());
DCHECK(!prop->IsSuperAccess());
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());
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())));
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);
}
// 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) {
__ 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) {
void FullCodeGenerator::VisitProperty(Property* expr) {
Comment cmnt(masm_, "[ Property");
+ SetExpressionPosition(expr);
+
Expression* key = expr->key();
if (key->IsPropertyName()) {
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.
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());
// 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));
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).
// 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);
+ // Push the arguments.
+ for (int i = 0; i < arg_count; i++) {
+ VisitForStackValue(args->at(i));
+ }
- // Touch up the stack with the resolved function.
- __ mov(Operand(esp, (arg_count + 1) * kPointerSize), eax);
+ // Push a copy of the function (found below the arguments) and
+ // resolve eval.
+ __ push(Operand(esp, (arg_count + 1) * kPointerSize));
+ EmitResolvePossiblyDirectEval(arg_count);
- PrepareForBailoutForId(expr->EvalId(), NO_REGISTERS);
- }
- // Record source position for debugger.
- SetSourcePosition(expr->position());
+ // 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);
EmitKeyedSuperCallWithLoadIC(expr);
}
} else {
- {
- PreservePositionScope scope(masm()->positions_recorder());
- VisitForStackValue(property->obj());
- }
+ VisitForStackValue(property->obj());
if (is_named_call) {
EmitCallWithLoadIC(expr);
} else {
} 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);
// 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));
// 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));
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);
DCHECK(expr->expression()->IsValidReferenceExpression());
Comment cmnt(masm_, "[ CountOperation");
- SetSourcePosition(expr->position());
Property* prop = expr->expression()->AsProperty();
LhsKind assign_type = Property::GetAssignType(prop);
}
}
- // Record position before stub call.
- SetSourcePosition(expr->position());
+ SetExpressionPosition(expr);
// Call stub for +1/-1.
__ bind(&stub_call);
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.
__ 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());
}
-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
// 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();
}
// 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());
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);
// 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);
// 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));
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();
DCHECK(expr->target()->IsValidReferenceExpression());
Comment cmnt(masm_, "[ Assignment");
+ SetExpressionPosition(expr, INSERT_BREAK);
Property* property = expr->target()->AsProperty();
LhsKind assign_type = Property::GetAssignType(property);
__ 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(),
VisitForAccumulatorValue(expr->value());
}
- // Record source position before possible IC call.
- SetSourcePosition(expr->position());
+ SetExpressionPosition(expr);
// Store the value.
switch (assign_type) {
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());
void FullCodeGenerator::EmitNamedPropertyLoad(Property* prop) {
- SetSourcePosition(prop->position());
+ SetExpressionPosition(prop);
Literal* key = prop->key()->AsLiteral();
DCHECK(!prop->IsSuperAccess());
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());
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())));
void FullCodeGenerator::EmitKeyedSuperPropertyLoad(Property* prop) {
// Stack: receiver, home_object, key.
+ SetExpressionPosition(prop);
__ Push(Smi::FromInt(language_mode()));
- SetSourcePosition(prop->position());
-
__ CallRuntime(Runtime::kLoadKeyedFromSuper, 4);
}
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()));
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,
void FullCodeGenerator::VisitProperty(Property* expr) {
Comment cmnt(masm_, "[ Property");
+ SetExpressionPosition(expr);
+
Expression* key = expr->key();
if (key->IsPropertyName()) {
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.
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();
// 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));
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)
// 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.
__ 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);
EmitKeyedSuperCallWithLoadIC(expr);
}
} else {
- {
- PreservePositionScope scope(masm()->positions_recorder());
VisitForStackValue(property->obj());
- }
if (is_named_call) {
EmitCallWithLoadIC(expr);
} else {
} 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.
// 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));
// 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));
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);
DCHECK(expr->expression()->IsValidReferenceExpression());
Comment cmnt(masm_, "[ CountOperation");
- SetSourcePosition(expr->position());
Property* prop = expr->expression()->AsProperty();
LhsKind assign_type = Property::GetAssignType(prop);
__ 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();
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.
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());
}
-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
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_);
// 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();
}
// 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());
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);
// 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);
// 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));
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();
DCHECK(expr->target()->IsValidReferenceExpression());
Comment cmnt(masm_, "[ Assignment");
+ SetExpressionPosition(expr, INSERT_BREAK);
Property* property = expr->target()->AsProperty();
LhsKind assign_type = Property::GetAssignType(property);
__ 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(),
VisitForAccumulatorValue(expr->value());
}
- // Record source position before possible IC call.
- SetSourcePosition(expr->position());
+ SetExpressionPosition(expr);
// Store the value.
switch (assign_type) {
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());
void FullCodeGenerator::EmitNamedPropertyLoad(Property* prop) {
- SetSourcePosition(prop->position());
+ SetExpressionPosition(prop);
Literal* key = prop->key()->AsLiteral();
DCHECK(!prop->IsSuperAccess());
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());
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())));
void FullCodeGenerator::EmitKeyedSuperPropertyLoad(Property* prop) {
// Stack: receiver, home_object, key.
+ SetExpressionPosition(prop);
__ Push(Smi::FromInt(language_mode()));
- SetSourcePosition(prop->position());
-
__ CallRuntime(Runtime::kLoadKeyedFromSuper, 4);
}
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()));
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,
void FullCodeGenerator::VisitProperty(Property* expr) {
Comment cmnt(masm_, "[ Property");
+ SetExpressionPosition(expr);
+
Expression* key = expr->key();
if (key->IsPropertyName()) {
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.
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();
// 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));
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)
// 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.
__ 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);
EmitKeyedSuperCallWithLoadIC(expr);
}
} else {
- {
- PreservePositionScope scope(masm()->positions_recorder());
VisitForStackValue(property->obj());
- }
if (is_named_call) {
EmitCallWithLoadIC(expr);
} else {
} 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.
// 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));
// 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));
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);
DCHECK(expr->expression()->IsValidReferenceExpression());
Comment cmnt(masm_, "[ CountOperation");
- SetSourcePosition(expr->position());
Property* prop = expr->expression()->AsProperty();
LhsKind assign_type = Property::GetAssignType(prop);
__ 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();
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.
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());
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,
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(
return loop;
} else {
- init = factory()->NewExpressionStatement(expression, position());
+ init =
+ factory()->NewExpressionStatement(expression, lhs_location.beg_pos);
}
}
}
}
-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 -------------
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.
}
// 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());
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);
// 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);
// 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.
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();
DCHECK(expr->target()->IsValidReferenceExpression());
Comment cmnt(masm_, "[ Assignment");
+ SetExpressionPosition(expr, INSERT_BREAK);
Property* property = expr->target()->AsProperty();
LhsKind assign_type = Property::GetAssignType(property);
__ 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(),
VisitForAccumulatorValue(expr->value());
}
- // Record source position before possible IC call.
- SetSourcePosition(expr->position());
+ SetExpressionPosition(expr);
// Store the value.
switch (assign_type) {
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());
void FullCodeGenerator::EmitNamedPropertyLoad(Property* prop) {
- SetSourcePosition(prop->position());
+ SetExpressionPosition(prop);
Literal* key = prop->key()->AsLiteral();
DCHECK(!prop->IsSuperAccess());
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());
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()));
void FullCodeGenerator::EmitKeyedSuperPropertyLoad(Property* prop) {
// Stack: receiver, home_object, key.
+ SetExpressionPosition(prop);
__ Push(Smi::FromInt(language_mode()));
- SetSourcePosition(prop->position());
-
__ CallRuntime(Runtime::kLoadKeyedFromSuper, 4);
}
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) {
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) {
void FullCodeGenerator::VisitProperty(Property* expr) {
Comment cmnt(masm_, "[ Property");
+ SetExpressionPosition(expr);
+
Expression* key = expr->key();
if (key->IsPropertyName()) {
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.
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());
// 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));
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).
// 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.
__ 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);
EmitKeyedSuperCallWithLoadIC(expr);
}
} else {
- {
- PreservePositionScope scope(masm()->positions_recorder());
VisitForStackValue(property->obj());
- }
if (is_named_call) {
EmitCallWithLoadIC(expr);
} else {
} 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);
// 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);
// 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);
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);
DCHECK(expr->expression()->IsValidReferenceExpression());
Comment cmnt(masm_, "[ CountOperation");
- SetSourcePosition(expr->position());
Property* prop = expr->expression()->AsProperty();
LhsKind assign_type = Property::GetAssignType(prop);
}
}
- // Record position before stub call.
- SetSourcePosition(expr->position());
+ SetExpressionPosition(expr);
// Call stub for +1/-1.
__ bind(&stub_call);
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.
__ 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());
// --- 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) {
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);
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;
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);
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);
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);
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);
// (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()"],
try {
throw 1;
} catch (e) {
- try{
+ try {
f1();
} catch (e) {
var v02 = 2; // Break 13
}
var v03 = 3;
var v04 = 4;
+ eval('var v05 = 5; // Break 14');
+ var v06 = 6; // Break 15
}
function f1() {
Debug.setListener(listener);
debugger; // Break 0
f0();
- Debug.setListener(null); // Break 14
+ Debug.setListener(null); // Break 16
assertTrue(break_count > 14);
}
if (!done) {
execState.prepareStep(Debug.StepAction.StepInto);
var s = execState.frame().sourceLineText();
+ print(s);
assertTrue(s.indexOf('// ' + stepCount + '.') !== -1);
stepCount++;
}
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.
}
}
var bp = Debug.setBreakPoint(Base, 0);
new Base();
- assertEquals(4, stepCount);
+ assertEquals(5, stepCount);
Debug.clearBreakPoint(bp);
})();
var bp = Debug.setBreakPoint(Base, 0);
new Derived();
- assertEquals(4, stepCount);
+ assertEquals(5, stepCount);
Debug.clearBreakPoint(bp);
})();
var bp = Debug.setBreakPoint(f, 0);
f();
- assertEquals(4, stepCount);
+ assertEquals(5, stepCount);
Debug.clearBreakPoint(bp);
})();
var bp = Debug.setBreakPoint(f, 0);
f();
- assertEquals(4, stepCount);
+ assertEquals(5, stepCount);
Debug.clearBreakPoint(bp);
})();
var bp = Debug.setBreakPoint(f, 0);
f();
- assertEquals(4, stepCount);
+ assertEquals(5, stepCount);
Debug.clearBreakPoint(bp);
})();
// 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",
]
'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],