Commit 88c4f52c authored by mstarzinger's avatar mstarzinger Committed by Commit bot

Emit exception handler table in TurboFan.

R=bmeurer@chromium.org

Review URL: https://codereview.chromium.org/943503003

Cr-Commit-Position: refs/heads/master@{#26783}
parent 40ebcea1
......@@ -313,7 +313,7 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
Operand(Code::kHeaderSize - kHeapObjectTag));
__ Call(ip);
}
AddSafepointAndDeopt(instr);
RecordCallPosition(instr);
DCHECK_EQ(LeaveCC, i.OutputSBit());
break;
}
......@@ -328,7 +328,7 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
}
__ ldr(ip, FieldMemOperand(func, JSFunction::kCodeEntryOffset));
__ Call(ip);
AddSafepointAndDeopt(instr);
RecordCallPosition(instr);
DCHECK_EQ(LeaveCC, i.OutputSBit());
break;
}
......
......@@ -1018,7 +1018,7 @@ void InstructionSelector::VisitFloat64RoundTiesAway(Node* node) {
}
void InstructionSelector::VisitCall(Node* node) {
void InstructionSelector::VisitCall(Node* node, BasicBlock* handler) {
ArmOperandGenerator g(this);
const CallDescriptor* descriptor = OpParameter<const CallDescriptor*>(node);
......@@ -1043,6 +1043,13 @@ void InstructionSelector::VisitCall(Node* node) {
Emit(kArmPush, g.NoOutput(), g.UseRegister(*i));
}
// Pass label of exception handler block.
CallDescriptor::Flags flags = descriptor->flags();
if (handler != nullptr) {
flags |= CallDescriptor::kHasExceptionHandler;
buffer.instruction_args.push_back(g.Label(handler));
}
// Select the appropriate opcode based on the call type.
InstructionCode opcode;
switch (descriptor->kind()) {
......@@ -1057,7 +1064,7 @@ void InstructionSelector::VisitCall(Node* node) {
UNREACHABLE();
return;
}
opcode |= MiscField::encode(descriptor->flags());
opcode |= MiscField::encode(flags);
// Emit the call instruction.
InstructionOperand* first_output =
......
......@@ -335,7 +335,7 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
__ Add(target, target, Code::kHeaderSize - kHeapObjectTag);
__ Call(target);
}
AddSafepointAndDeopt(instr);
RecordCallPosition(instr);
break;
}
case kArchCallJSFunction: {
......@@ -351,7 +351,7 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
}
__ Ldr(x10, FieldMemOperand(func, JSFunction::kCodeEntryOffset));
__ Call(x10);
AddSafepointAndDeopt(instr);
RecordCallPosition(instr);
break;
}
case kArchJmp:
......
......@@ -1080,7 +1080,7 @@ void InstructionSelector::VisitFloat64RoundTiesAway(Node* node) {
}
void InstructionSelector::VisitCall(Node* node) {
void InstructionSelector::VisitCall(Node* node, BasicBlock* handler) {
Arm64OperandGenerator g(this);
const CallDescriptor* descriptor = OpParameter<const CallDescriptor*>(node);
......@@ -1127,6 +1127,13 @@ void InstructionSelector::VisitCall(Node* node) {
}
}
// Pass label of exception handler block.
CallDescriptor::Flags flags = descriptor->flags();
if (handler != nullptr) {
flags |= CallDescriptor::kHasExceptionHandler;
buffer.instruction_args.push_back(g.Label(handler));
}
// Select the appropriate opcode based on the call type.
InstructionCode opcode;
switch (descriptor->kind()) {
......@@ -1141,7 +1148,7 @@ void InstructionSelector::VisitCall(Node* node) {
UNREACHABLE();
return;
}
opcode |= MiscField::encode(descriptor->flags());
opcode |= MiscField::encode(flags);
// Emit the call instruction.
InstructionOperand* first_output =
......
......@@ -42,6 +42,7 @@ CodeGenerator::CodeGenerator(Frame* frame, Linkage* linkage,
masm_(info->isolate(), NULL, 0),
resolver_(this),
safepoints_(code->zone()),
handlers_(code->zone()),
deoptimization_states_(code->zone()),
deoptimization_literals_(code->zone()),
translations_(code->zone()),
......@@ -131,6 +132,18 @@ Handle<Code> CodeGenerator::GenerateCode() {
result->set_stack_slots(frame()->GetSpillSlotCount());
result->set_safepoint_table_offset(safepoints()->GetCodeOffset());
// Emit exception handler table.
if (!handlers_.empty()) {
Handle<FixedArray> table = isolate()->factory()->NewFixedArray(
static_cast<int>(handlers_.size()) * 2, TENURED);
for (size_t i = 0; i < handlers_.size(); ++i) {
int table_index = static_cast<int>(i * 2);
table->set(table_index + 0, Smi::FromInt(handlers_[i].pc_offset));
table->set(table_index + 1, Smi::FromInt(handlers_[i].handler->pos()));
}
result->set_handler_table(*table);
}
PopulateDeoptimizationData(result);
// Ensure there is space for lazy deoptimization in the relocation info.
......@@ -321,7 +334,7 @@ Label* CodeGenerator::AddJumpTable(Label** targets, size_t target_count) {
}
void CodeGenerator::AddSafepointAndDeopt(Instruction* instr) {
void CodeGenerator::RecordCallPosition(Instruction* instr) {
CallDescriptor::Flags flags(MiscField::decode(instr->opcode()));
bool needs_frame_state = (flags & CallDescriptor::kNeedsFrameState);
......@@ -330,16 +343,21 @@ void CodeGenerator::AddSafepointAndDeopt(Instruction* instr) {
instr->pointer_map(), Safepoint::kSimple, 0,
needs_frame_state ? Safepoint::kLazyDeopt : Safepoint::kNoLazyDeopt);
if (flags & CallDescriptor::kHasExceptionHandler) {
InstructionOperandConverter i(this, instr);
BasicBlock::RpoNumber handler_rpo =
i.InputRpo(static_cast<int>(instr->InputCount()) - 1);
handlers_.push_back({GetLabel(handler_rpo), masm()->pc_offset()});
}
if (flags & CallDescriptor::kNeedsNopAfterCall) {
AddNopForSmiCodeInlining();
}
if (needs_frame_state) {
MarkLazyDeoptSite();
// If the frame state is present, it starts at argument 1
// (just after the code address).
InstructionOperandConverter converter(this, instr);
// Deoptimization info starts at argument 1
// If the frame state is present, it starts at argument 1 (just after the
// code address).
size_t frame_state_offset = 1;
FrameStateDescriptor* descriptor =
GetFrameStateDescriptor(instr, frame_state_offset);
......
......@@ -106,8 +106,10 @@ class CodeGenerator FINAL : public GapResolver::Assembler {
void AssembleJumpTable(Label** targets, size_t target_count);
// ===========================================================================
// Deoptimization table construction
void AddSafepointAndDeopt(Instruction* instr);
// ================== Deoptimization table construction. =====================
// ===========================================================================
void RecordCallPosition(Instruction* instr);
void PopulateDeoptimizationData(Handle<Code> code);
int DefineDeoptimizationLiteral(Handle<Object> literal);
FrameStateDescriptor* GetFrameStateDescriptor(Instruction* instr,
......@@ -126,6 +128,7 @@ class CodeGenerator FINAL : public GapResolver::Assembler {
void MarkLazyDeoptSite();
// ===========================================================================
struct DeoptimizationState : ZoneObject {
public:
BailoutId bailout_id() const { return bailout_id_; }
......@@ -143,6 +146,11 @@ class CodeGenerator FINAL : public GapResolver::Assembler {
int pc_offset_;
};
struct HandlerInfo {
Label* handler;
int pc_offset;
};
friend class OutOfLineCode;
Frame* const frame_;
......@@ -155,8 +163,9 @@ class CodeGenerator FINAL : public GapResolver::Assembler {
MacroAssembler masm_;
GapResolver resolver_;
SafepointTableBuilder safepoints_;
ZoneVector<HandlerInfo> handlers_;
ZoneDeque<DeoptimizationState*> deoptimization_states_;
ZoneDeque<Handle<Object> > deoptimization_literals_;
ZoneDeque<Handle<Object>> deoptimization_literals_;
TranslationBuffer translations_;
int last_lazy_deopt_pc_;
JumpTable* jump_tables_;
......
......@@ -292,7 +292,7 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
Register reg = i.InputRegister(0);
__ call(Operand(reg, Code::kHeaderSize - kHeapObjectTag));
}
AddSafepointAndDeopt(instr);
RecordCallPosition(instr);
break;
}
case kArchCallJSFunction: {
......@@ -304,7 +304,7 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
__ Assert(equal, kWrongFunctionContext);
}
__ call(FieldOperand(func, JSFunction::kCodeEntryOffset));
AddSafepointAndDeopt(instr);
RecordCallPosition(instr);
break;
}
case kArchJmp:
......
......@@ -718,7 +718,7 @@ void InstructionSelector::VisitFloat64RoundTiesAway(Node* node) {
}
void InstructionSelector::VisitCall(Node* node) {
void InstructionSelector::VisitCall(Node* node, BasicBlock* handler) {
IA32OperandGenerator g(this);
const CallDescriptor* descriptor = OpParameter<const CallDescriptor*>(node);
......@@ -745,6 +745,13 @@ void InstructionSelector::VisitCall(Node* node) {
Emit(kIA32Push, g.NoOutput(), value);
}
// Pass label of exception handler block.
CallDescriptor::Flags flags = descriptor->flags();
if (handler != nullptr) {
flags |= CallDescriptor::kHasExceptionHandler;
buffer.instruction_args.push_back(g.Label(handler));
}
// Select the appropriate opcode based on the call type.
InstructionCode opcode;
switch (descriptor->kind()) {
......@@ -759,7 +766,7 @@ void InstructionSelector::VisitCall(Node* node) {
UNREACHABLE();
return;
}
opcode |= MiscField::encode(descriptor->flags());
opcode |= MiscField::encode(flags);
// Emit the call instruction.
InstructionOperand* first_output =
......
......@@ -505,9 +505,8 @@ void InstructionSelector::VisitControl(BasicBlock* block) {
case BasicBlock::kCall: {
DCHECK_EQ(IrOpcode::kCall, input->opcode());
BasicBlock* success = block->SuccessorAt(0);
// TODO(mstarzinger): Record location of {exception} in {handler_table}.
// BasicBlock* exception = block->SuccessorAt(1);
return VisitCall(input), VisitGoto(success);
BasicBlock* exception = block->SuccessorAt(1);
return VisitCall(input, exception), VisitGoto(success);
}
case BasicBlock::kBranch: {
DCHECK_EQ(IrOpcode::kBranch, input->opcode());
......@@ -756,7 +755,7 @@ void InstructionSelector::VisitNode(Node* node) {
return VisitConstant(node);
}
case IrOpcode::kCall:
return VisitCall(node);
return VisitCall(node, nullptr);
case IrOpcode::kFrameState:
case IrOpcode::kStateValues:
return;
......
......@@ -199,7 +199,7 @@ class InstructionSelector FINAL {
void VisitPhi(Node* node);
void VisitProjection(Node* node);
void VisitConstant(Node* node);
void VisitCall(Node* call);
void VisitCall(Node* call, BasicBlock* handler);
void VisitGoto(BasicBlock* target);
void VisitBranch(Node* input, BasicBlock* tbranch, BasicBlock* fbranch);
void VisitSwitch(Node* node, BasicBlock* default_branch,
......
......@@ -56,11 +56,11 @@ class CallDescriptor FINAL : public ZoneObject {
};
enum Flag {
// TODO(jarin) kLazyDeoptimization and kNeedsFrameState should be unified.
kNoFlags = 0u,
kNeedsFrameState = 1u << 0,
kPatchableCallSite = 1u << 1,
kNeedsNopAfterCall = 1u << 2,
kHasExceptionHandler = 1u << 3,
kPatchableCallSiteWithNop = kPatchableCallSite | kNeedsNopAfterCall
};
typedef base::Flags<Flag> Flags;
......
......@@ -408,7 +408,7 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
__ addiu(at, i.InputRegister(0), Code::kHeaderSize - kHeapObjectTag);
__ Call(at);
}
AddSafepointAndDeopt(instr);
RecordCallPosition(instr);
break;
}
case kArchCallJSFunction: {
......@@ -422,7 +422,7 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
__ lw(at, FieldMemOperand(func, JSFunction::kCodeEntryOffset));
__ Call(at);
AddSafepointAndDeopt(instr);
RecordCallPosition(instr);
break;
}
case kArchJmp:
......
......@@ -449,7 +449,7 @@ void InstructionSelector::VisitFloat64RoundTiesAway(Node* node) {
}
void InstructionSelector::VisitCall(Node* node) {
void InstructionSelector::VisitCall(Node* node, BasicBlock* handler) {
MipsOperandGenerator g(this);
const CallDescriptor* descriptor = OpParameter<const CallDescriptor*>(node);
......@@ -476,6 +476,13 @@ void InstructionSelector::VisitCall(Node* node) {
slot--;
}
// Pass label of exception handler block.
CallDescriptor::Flags flags = descriptor->flags();
if (handler != nullptr) {
flags |= CallDescriptor::kHasExceptionHandler;
buffer.instruction_args.push_back(g.Label(handler));
}
// Select the appropriate opcode based on the call type.
InstructionCode opcode;
switch (descriptor->kind()) {
......@@ -490,7 +497,7 @@ void InstructionSelector::VisitCall(Node* node) {
UNREACHABLE();
return;
}
opcode |= MiscField::encode(descriptor->flags());
opcode |= MiscField::encode(flags);
// Emit the call instruction.
InstructionOperand* first_output =
......
......@@ -408,7 +408,7 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
__ daddiu(at, i.InputRegister(0), Code::kHeaderSize - kHeapObjectTag);
__ Call(at);
}
AddSafepointAndDeopt(instr);
RecordCallPosition(instr);
break;
}
case kArchCallJSFunction: {
......@@ -422,7 +422,7 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
__ ld(at, FieldMemOperand(func, JSFunction::kCodeEntryOffset));
__ Call(at);
AddSafepointAndDeopt(instr);
RecordCallPosition(instr);
break;
}
case kArchJmp:
......
......@@ -629,7 +629,7 @@ void InstructionSelector::VisitFloat64RoundTiesAway(Node* node) {
}
void InstructionSelector::VisitCall(Node* node) {
void InstructionSelector::VisitCall(Node* node, BasicBlock* handler) {
Mips64OperandGenerator g(this);
const CallDescriptor* descriptor = OpParameter<const CallDescriptor*>(node);
......@@ -656,6 +656,13 @@ void InstructionSelector::VisitCall(Node* node) {
slot--;
}
// Pass label of exception handler block.
CallDescriptor::Flags flags = descriptor->flags();
if (handler != nullptr) {
flags |= CallDescriptor::kHasExceptionHandler;
buffer.instruction_args.push_back(g.Label(handler));
}
// Select the appropriate opcode based on the call type.
InstructionCode opcode;
switch (descriptor->kind()) {
......@@ -670,7 +677,7 @@ void InstructionSelector::VisitCall(Node* node) {
UNREACHABLE();
return;
}
opcode |= MiscField::encode(descriptor->flags());
opcode |= MiscField::encode(flags);
// Emit the call instruction.
Instruction* call_instr =
......
......@@ -532,7 +532,7 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
__ Call(Handle<Code>::cast(i.InputHeapObject(0)),
RelocInfo::CODE_TARGET);
}
AddSafepointAndDeopt(instr);
RecordCallPosition(instr);
DCHECK_EQ(LeaveRC, i.OutputRCBit());
break;
}
......@@ -548,7 +548,7 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
}
__ LoadP(ip, FieldMemOperand(func, JSFunction::kCodeEntryOffset));
__ Call(ip);
AddSafepointAndDeopt(instr);
RecordCallPosition(instr);
DCHECK_EQ(LeaveRC, i.OutputRCBit());
break;
}
......
......@@ -1378,7 +1378,7 @@ void InstructionSelector::VisitFloat64LessThanOrEqual(Node* node) {
}
void InstructionSelector::VisitCall(Node* node) {
void InstructionSelector::VisitCall(Node* node, BasicBlock* handler) {
PPCOperandGenerator g(this);
const CallDescriptor* descriptor = OpParameter<CallDescriptor*>(node);
......@@ -1403,6 +1403,13 @@ void InstructionSelector::VisitCall(Node* node) {
Emit(kPPC_Push, g.NoOutput(), g.UseRegister(*i));
}
// Pass label of exception handler block.
CallDescriptor::Flags flags = descriptor->flags();
if (handler != nullptr) {
flags |= CallDescriptor::kHasExceptionHandler;
buffer.instruction_args.push_back(g.Label(handler));
}
// Select the appropriate opcode based on the call type.
InstructionCode opcode;
switch (descriptor->kind()) {
......@@ -1417,7 +1424,7 @@ void InstructionSelector::VisitCall(Node* node) {
UNREACHABLE();
return;
}
opcode |= MiscField::encode(descriptor->flags());
opcode |= MiscField::encode(flags);
// Emit the call instruction.
InstructionOperand* first_output =
......
......@@ -526,7 +526,7 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
int entry = Code::kHeaderSize - kHeapObjectTag;
__ Call(Operand(reg, entry));
}
AddSafepointAndDeopt(instr);
RecordCallPosition(instr);
break;
}
case kArchCallJSFunction: {
......@@ -538,7 +538,7 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
__ Assert(equal, kWrongFunctionContext);
}
__ Call(FieldOperand(func, JSFunction::kCodeEntryOffset));
AddSafepointAndDeopt(instr);
RecordCallPosition(instr);
break;
}
case kArchJmp:
......
......@@ -940,7 +940,7 @@ void InstructionSelector::VisitFloat64RoundTiesAway(Node* node) {
}
void InstructionSelector::VisitCall(Node* node) {
void InstructionSelector::VisitCall(Node* node, BasicBlock* handler) {
X64OperandGenerator g(this);
const CallDescriptor* descriptor = OpParameter<const CallDescriptor*>(node);
......@@ -966,6 +966,13 @@ void InstructionSelector::VisitCall(Node* node) {
Emit(kX64Push, g.NoOutput(), value);
}
// Pass label of exception handler block.
CallDescriptor::Flags flags = descriptor->flags();
if (handler != nullptr) {
flags |= CallDescriptor::kHasExceptionHandler;
buffer.instruction_args.push_back(g.Label(handler));
}
// Select the appropriate opcode based on the call type.
InstructionCode opcode;
switch (descriptor->kind()) {
......@@ -980,7 +987,7 @@ void InstructionSelector::VisitCall(Node* node) {
UNREACHABLE();
return;
}
opcode |= MiscField::encode(descriptor->flags());
opcode |= MiscField::encode(flags);
// Emit the call instruction.
InstructionOperand* first_output =
......
......@@ -11828,6 +11828,19 @@ void Code::Disassemble(const char* name, std::ostream& os) { // NOLINT
#endif
}
if (handler_table()->length() > 0 && is_turbofanned()) {
os << "Handler Table (size = " << handler_table()->Size() << ")\n";
for (int i = 0; i < handler_table()->length(); i += 2) {
int pc_offset = Smi::cast(handler_table()->get(i))->value();
int handler = Smi::cast(handler_table()->get(i + 1))->value();
os << static_cast<const void*>(instruction_start() + pc_offset) << " ";
Vector<char> buf = Vector<char>::New(20);
SNPrintF(buf, "%4d %4d\n", pc_offset, handler);
os << buf.start();
}
os << "\n";
}
os << "RelocInfo (size = " << relocation_size() << ")\n";
for (RelocIterator it(this); !it.done(); it.next()) {
it.rinfo()->Print(GetIsolate(), os);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment