Reviewers: Benedikt Meurer,

Message:
First round of comments before I do the ports would be awesome. Thanks!

Description:
Emit exception handler table in TurboFan.

[email protected]

Please review this at https://codereview.chromium.org/943503003/

Base URL: https://chromium.googlesource.com/v8/v8.git@local_trycatch-4

Affected files (+64, -18 lines):
  M src/compiler/code-generator.h
  M src/compiler/code-generator.cc
  M src/compiler/ia32/code-generator-ia32.cc
  M src/compiler/ia32/instruction-selector-ia32.cc
  M src/compiler/instruction-selector.h
  M src/compiler/instruction-selector.cc
  M src/compiler/linkage.h
  M src/objects.cc


Index: src/compiler/code-generator.cc
diff --git a/src/compiler/code-generator.cc b/src/compiler/code-generator.cc
index 1a4566d60994dbba96e72fcde285c215d5f2120e..9a466cfc77c70d54b4428d1fb699db82b9f9c954 100644
--- a/src/compiler/code-generator.cc
+++ b/src/compiler/code-generator.cc
@@ -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_.size() > 0) {
+    Handle<FixedArray> table =
+        isolate()->factory()->NewFixedArray(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::AddSafepointAndDeoptAndHandler(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);
Index: src/compiler/code-generator.h
diff --git a/src/compiler/code-generator.h b/src/compiler/code-generator.h
index 658394b3217ad79b00bfe632425f495dfd3f13e9..d563ab7a2554c8f6ecc328693b7cb078230b2790 100644
--- a/src/compiler/code-generator.h
+++ b/src/compiler/code-generator.h
@@ -27,6 +27,12 @@ struct BranchInfo {
 };


+struct HandlerInfo {
+  Label* handler;
+  int pc_offset;
+};
+
+
 // Generates native code for a sequence of instructions.
 class CodeGenerator FINAL : public GapResolver::Assembler {
  public:
@@ -106,8 +112,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 AddSafepointAndDeoptAndHandler(Instruction* instr);
   void PopulateDeoptimizationData(Handle<Code> code);
   int DefineDeoptimizationLiteral(Handle<Object> literal);
   FrameStateDescriptor* GetFrameStateDescriptor(Instruction* instr,
@@ -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_;
Index: src/compiler/ia32/code-generator-ia32.cc
diff --git a/src/compiler/ia32/code-generator-ia32.cc b/src/compiler/ia32/code-generator-ia32.cc index d20848918d30aad46f247217479f0e6b9e39544c..1bf3ffdb792c13347692350099aa681776396a24 100644
--- a/src/compiler/ia32/code-generator-ia32.cc
+++ b/src/compiler/ia32/code-generator-ia32.cc
@@ -292,7 +292,7 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
         Register reg = i.InputRegister(0);
         __ call(Operand(reg, Code::kHeaderSize - kHeapObjectTag));
       }
-      AddSafepointAndDeopt(instr);
+      AddSafepointAndDeoptAndHandler(instr);
       break;
     }
     case kArchCallJSFunction: {
@@ -304,7 +304,7 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
         __ Assert(equal, kWrongFunctionContext);
       }
       __ call(FieldOperand(func, JSFunction::kCodeEntryOffset));
-      AddSafepointAndDeopt(instr);
+      AddSafepointAndDeoptAndHandler(instr);
       break;
     }
     case kArchJmp:
Index: src/compiler/ia32/instruction-selector-ia32.cc
diff --git a/src/compiler/ia32/instruction-selector-ia32.cc b/src/compiler/ia32/instruction-selector-ia32.cc index beec701903ec4598f26fb3d093b7898b2ea27804..2ca56a480e9579b4e023f41d88329d541caaf503 100644
--- a/src/compiler/ia32/instruction-selector-ia32.cc
+++ b/src/compiler/ia32/instruction-selector-ia32.cc
@@ -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;
+  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(descriptor->flags() | flags);

   // Emit the call instruction.
   InstructionOperand* first_output =
Index: src/compiler/instruction-selector.cc
diff --git a/src/compiler/instruction-selector.cc b/src/compiler/instruction-selector.cc index 2d0b2bd8af18c44af2b4691d306ee2ed42713045..d007fbf13d57fc00e8b20c6455bc981ad176633a 100644
--- a/src/compiler/instruction-selector.cc
+++ b/src/compiler/instruction-selector.cc
@@ -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;
Index: src/compiler/instruction-selector.h
diff --git a/src/compiler/instruction-selector.h b/src/compiler/instruction-selector.h index 5c31db74e9a158dd495283fbfe3f119768850530..0776ec54fc2196db8213197a2bb361779d27a02c 100644
--- a/src/compiler/instruction-selector.h
+++ b/src/compiler/instruction-selector.h
@@ -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,
Index: src/compiler/linkage.h
diff --git a/src/compiler/linkage.h b/src/compiler/linkage.h
index a3bdbf9d5bc84671a8441f1ca80c7a5c6c728c9f..a4b587dc4499407ec711d7896d70ed21d9b94736 100644
--- a/src/compiler/linkage.h
+++ b/src/compiler/linkage.h
@@ -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;
Index: src/objects.cc
diff --git a/src/objects.cc b/src/objects.cc
index 7459ed4525b2d96df98729803fddc17fbbdf2227..c5285e6ee6591554f598f858bfab2d218a3accc9 100644
--- a/src/objects.cc
+++ b/src/objects.cc
@@ -11713,6 +11713,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);


--
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
--- You received this message because you are subscribed to the Google Groups "v8-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/d/optout.

Reply via email to