Reviewers: ulan,

Message:
PTAL

Description:
Elide unnecessary context reload in generated stubs.


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

SVN Base: https://v8.googlecode.com/svn/branches/bleeding_edge

Affected files:
  M src/arm/lithium-arm.cc
  M src/arm/lithium-codegen-arm.cc
  M src/code-stubs-hydrogen.cc
  M src/hydrogen-instructions.h
  M src/hydrogen.cc
  M src/ia32/lithium-codegen-ia32.cc
  M src/ia32/lithium-ia32.h
  M src/ia32/lithium-ia32.cc
  M src/lithium-allocator-inl.h
  M src/lithium-allocator.cc
  M src/x64/lithium-codegen-x64.cc
  M src/x64/lithium-x64.cc


Index: src/arm/lithium-arm.cc
diff --git a/src/arm/lithium-arm.cc b/src/arm/lithium-arm.cc
index f44ca98aad059da26ffb7bfeb6aa320d9247e5ca..fd55e2460fcbfa2242057be35b096dabec5b3725 100644
--- a/src/arm/lithium-arm.cc
+++ b/src/arm/lithium-arm.cc
@@ -999,7 +999,14 @@ LInstruction* LChunkBuilder::DoThisFunction(HThisFunction* instr) {


 LInstruction* LChunkBuilder::DoContext(HContext* instr) {
- return instr->HasNoUses() ? NULL : DefineAsRegister(new(zone()) LContext); + // If there is a non-return use, the context must be allocated in a register.
+  for (HUseIterator it(instr->uses()); !it.Done(); it.Advance()) {
+    if (!it.value()->IsReturn()) {
+      return DefineAsRegister(new(zone()) LContext);
+    }
+  }
+
+  return NULL;
 }


Index: src/arm/lithium-codegen-arm.cc
diff --git a/src/arm/lithium-codegen-arm.cc b/src/arm/lithium-codegen-arm.cc
index 53d99814bb5d56cc10cb7c1aaed206f730ce1c3d..aedd48584320031919050edb3f5e72b99c3467f9 100644
--- a/src/arm/lithium-codegen-arm.cc
+++ b/src/arm/lithium-codegen-arm.cc
@@ -2765,9 +2765,6 @@ void LCodeGen::DoReturn(LReturn* instr) {
     __ ldm(ia_w, sp, fp.bit() | lr.bit());
     __ add(sp, sp, Operand(sp_delta));
   }
-  if (info()->IsStub()) {
-    __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
-  }
   __ Jump(lr);
 }

Index: src/code-stubs-hydrogen.cc
diff --git a/src/code-stubs-hydrogen.cc b/src/code-stubs-hydrogen.cc
index 74bd93f8805b768fbcb9806d2da04f754c80dfff..58e17f43f2adf7f98883e97db94b7297710949cb 100644
--- a/src/code-stubs-hydrogen.cc
+++ b/src/code-stubs-hydrogen.cc
@@ -51,17 +51,19 @@ Handle<Code> HydrogenCodeStub::CodeFromGraph(HGraph* graph) {
 class CodeStubGraphBuilderBase : public HGraphBuilder {
  public:
   CodeStubGraphBuilderBase(Isolate* isolate, HydrogenCodeStub* stub)
-      : HGraphBuilder(&info_), info_(stub, isolate) {}
+      : HGraphBuilder(&info_), info_(stub, isolate), context_(NULL) {}
   virtual bool BuildGraph();

  protected:
   virtual void BuildCodeStub() = 0;
HParameter* GetParameter(int parameter) { return parameters_[parameter]; }
   HydrogenCodeStub* stub() { return info_.code_stub(); }
+  HContext* context() { return context_; }

  private:
   SmartArrayPointer<HParameter*> parameters_;
   CompilationInfoWithZone info_;
+  HContext* context_;
 };


@@ -77,6 +79,9 @@ bool CodeStubGraphBuilderBase::BuildGraph() {
   graph()->entry_block()->Finish(jump);
   set_current_block(next_block);

+  context_ = new(zone()) HContext();
+  AddInstruction(context_);
+
   int major_key = stub()->MajorKey();
   CodeStubInterfaceDescriptor* descriptor =
       info_.isolate()->code_stub_interface_descriptor(major_key);
@@ -121,7 +126,7 @@ void CodeStubGraphBuilder<KeyedLoadFastElementStub>::BuildCodeStub() {
       casted_stub()->is_js_array(), casted_stub()->elements_kind(), false);
   AddInstruction(load);

-  HReturn* ret = new(zone) HReturn(load);
+  HReturn* ret = new(zone) HReturn(load, context());
   current_block()->Finish(ret);
 }

Index: src/hydrogen-instructions.h
diff --git a/src/hydrogen-instructions.h b/src/hydrogen-instructions.h
index d8f5dec0f7d90b4bc93c9da0da0e604dd0e65050..ee3fd9ba16818b30144d67b18c80425fa7515e73 100644
--- a/src/hydrogen-instructions.h
+++ b/src/hydrogen-instructions.h
@@ -1171,10 +1171,11 @@ class HCompareMap: public HUnaryControlInstruction {
 };


-class HReturn: public HTemplateControlInstruction<0, 1> {
+class HReturn: public HTemplateControlInstruction<0, 2> {
  public:
-  explicit HReturn(HValue* value) {
+  HReturn(HValue* value, HValue* context) {
     SetOperandAt(0, value);
+    SetOperandAt(1, context);
   }

   virtual Representation RequiredInputRepresentation(int index) {
@@ -1184,6 +1185,7 @@ class HReturn: public HTemplateControlInstruction<0, 1> {
   virtual void PrintDataTo(StringStream* stream);

   HValue* value() { return OperandAt(0); }
+  HValue* context() { return OperandAt(1); }

   DECLARE_CONCRETE_INSTRUCTION(Return)
 };
Index: src/hydrogen.cc
diff --git a/src/hydrogen.cc b/src/hydrogen.cc
index 7100d3a97ab930e57f7b5d5cd2c186201a31da41..97489a97c0742d2ec94bba60598106cb027a3813 100644
--- a/src/hydrogen.cc
+++ b/src/hydrogen.cc
@@ -3399,7 +3399,8 @@ bool HOptimizedGraphBuilder::BuildGraph() {
   if (HasStackOverflow()) return false;

   if (current_block() != NULL) {
-    HReturn* instr = new(zone()) HReturn(graph()->GetConstantUndefined());
+    HReturn* instr = new(zone()) HReturn(graph()->GetConstantUndefined(),
+                                         context);
     current_block()->FinishExit(instr);
     set_current_block(NULL);
   }
@@ -4215,7 +4216,9 @@ void HOptimizedGraphBuilder::VisitReturnStatement(ReturnStatement* stmt) {
     // Not an inlined return, so an actual one.
     CHECK_ALIVE(VisitForValue(stmt->expression()));
     HValue* result = environment()->Pop();
-    current_block()->FinishExit(new(zone()) HReturn(result));
+    current_block()->FinishExit(new(zone()) HReturn(
+        result,
+        environment()->LookupContext()));
   } else if (state->inlining_kind() == CONSTRUCT_CALL_RETURN) {
// Return from an inlined construct call. In a test context the return value // will always evaluate to true, in a value context the return value needs
Index: src/ia32/lithium-codegen-ia32.cc
diff --git a/src/ia32/lithium-codegen-ia32.cc b/src/ia32/lithium-codegen-ia32.cc index b2ce5203c511d096b7f300c290100aea80418d26..7e2f6ee7b1eb5c9d3074b9574df771c679be9012 100644
--- a/src/ia32/lithium-codegen-ia32.cc
+++ b/src/ia32/lithium-codegen-ia32.cc
@@ -804,7 +804,7 @@ void LCodeGen::DeoptimizeIf(Condition cc, LEnvironment* environment) {
   ASSERT(environment->HasBeenRegistered());
   int id = environment->deoptimization_index();
   ASSERT(info()->IsOptimizing() || info()->IsStub());
-  Deoptimizer::BailoutType bailout_type = frame_is_built_
+  Deoptimizer::BailoutType bailout_type = info()->IsOptimizing()
       ? Deoptimizer::EAGER
       : Deoptimizer::LAZY;
   Address entry = Deoptimizer::GetDeoptimizationEntry(id, bailout_type);
@@ -2640,7 +2640,6 @@ void LCodeGen::DoReturn(LReturn* instr) {
     __ bind(&no_padding);
   }
   if (info()->IsStub()) {
-    __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
     __ Ret();
   } else {
     __ Ret((GetParameterCount() + 1) * kPointerSize, ecx);
@@ -3375,7 +3374,12 @@ void LCodeGen::DoThisFunction(LThisFunction* instr) {

 void LCodeGen::DoContext(LContext* instr) {
   Register result = ToRegister(instr->result());
-  __ mov(result, Operand(ebp, StandardFrameConstants::kContextOffset));
+  if (info()->IsOptimizing()) {
+    __ mov(result, Operand(ebp, StandardFrameConstants::kContextOffset));
+  } else {
+    // If there is no frame, the context must be in esi.
+    ASSERT(result.is(esi));
+  }
 }


Index: src/ia32/lithium-ia32.cc
diff --git a/src/ia32/lithium-ia32.cc b/src/ia32/lithium-ia32.cc
index 6e075937977f83461a7ab19be17c061a4be23a49..46d8f408823c0d20cc66693b26469b5f75dd8a93 100644
--- a/src/ia32/lithium-ia32.cc
+++ b/src/ia32/lithium-ia32.cc
@@ -1055,7 +1055,13 @@ LInstruction* LChunkBuilder::DoThisFunction(HThisFunction* instr) {


 LInstruction* LChunkBuilder::DoContext(HContext* instr) {
- return instr->HasNoUses() ? NULL : DefineAsRegister(new(zone()) LContext);
+  if (instr->HasNoUses()) return NULL;
+
+  if (info()->IsStub()) {
+    return DefineFixed(new(zone()) LContext, esi);
+  }
+
+  return DefineAsRegister(new(zone()) LContext);
 }


@@ -1865,7 +1871,10 @@ LInstruction* LChunkBuilder::DoClampToUint8(HClampToUint8* instr) {


 LInstruction* LChunkBuilder::DoReturn(HReturn* instr) {
-  return new(zone()) LReturn(UseFixed(instr->value(), eax));
+  LOperand* context = info()->IsStub()
+      ? UseFixed(instr->context(), esi)
+      : NULL;
+  return new(zone()) LReturn(UseFixed(instr->value(), eax), context);
 }


Index: src/ia32/lithium-ia32.h
diff --git a/src/ia32/lithium-ia32.h b/src/ia32/lithium-ia32.h
index f4056c10d9115b8652b713f8a66c13ba526b6030..59b23d429c1e8f79c953d1d409bd1174793f16ef 100644
--- a/src/ia32/lithium-ia32.h
+++ b/src/ia32/lithium-ia32.h
@@ -1342,10 +1342,11 @@ class LArithmeticT: public LTemplateInstruction<1, 3, 0> {
 };


-class LReturn: public LTemplateInstruction<0, 1, 0> {
+class LReturn: public LTemplateInstruction<0, 2, 0> {
  public:
-  explicit LReturn(LOperand* value) {
+  explicit LReturn(LOperand* value, LOperand* context) {
     inputs_[0] = value;
+    inputs_[1] = context;
   }

   DECLARE_CONCRETE_INSTRUCTION(Return, "return")
Index: src/lithium-allocator-inl.h
diff --git a/src/lithium-allocator-inl.h b/src/lithium-allocator-inl.h
index 8f660ce0e00373bdd5521b183527e972fc68c75c..29b81848ceb33fc188b897da526ec9a56235d7bf 100644
--- a/src/lithium-allocator-inl.h
+++ b/src/lithium-allocator-inl.h
@@ -110,7 +110,10 @@ void InputIterator::Advance() {


 void InputIterator::SkipUninteresting() {
- while (current_ < limit_ && instr_->InputAt(current_)->IsConstantOperand()) {
+  LOperand* current;
+  while (current_ < limit_ &&
+         (current = instr_->InputAt(current_)) != NULL &&
+         current->IsConstantOperand()) {
     ++current_;
   }
 }
Index: src/lithium-allocator.cc
diff --git a/src/lithium-allocator.cc b/src/lithium-allocator.cc
index b23c86766a6fb71e86927aebefdd1b2034aab359..dcaa91e8662860ea21619ff27fa93e66a76c1e4c 100644
--- a/src/lithium-allocator.cc
+++ b/src/lithium-allocator.cc
@@ -830,6 +830,7 @@ void LAllocator::MeetConstraintsBetween(LInstruction* first,
   // Handle fixed input operands of second instruction.
   if (second != NULL) {
     for (UseIterator it(second); !it.Done(); it.Advance()) {
+      if (it.Current() == NULL) continue;
       LUnallocated* cur_input = LUnallocated::cast(it.Current());
       if (cur_input->HasFixedPolicy()) {
         LUnallocated* input_copy = cur_input->CopyUnconstrained(zone());
@@ -973,6 +974,7 @@ void LAllocator::ProcessInstructions(HBasicBlock* block, BitVector* live) {

         for (UseIterator it(instr); !it.Done(); it.Advance()) {
           LOperand* input = it.Current();
+          if (input == NULL) continue;

           LifetimePosition use_pos;
           if (input->IsUnallocated() &&
Index: src/x64/lithium-codegen-x64.cc
diff --git a/src/x64/lithium-codegen-x64.cc b/src/x64/lithium-codegen-x64.cc
index 2a10a87ac71e3868e344c9cc2a004cf0ef89a372..ad5469ecb1bc323253c6c73b4be9d0d9b8f52452 100644
--- a/src/x64/lithium-codegen-x64.cc
+++ b/src/x64/lithium-codegen-x64.cc
@@ -2441,7 +2441,6 @@ void LCodeGen::DoReturn(LReturn* instr) {
     __ pop(rbp);
   }
   if (info()->IsStub()) {
-    __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
     __ Ret(0, r10);
   } else {
     __ Ret((GetParameterCount() + 1) * kPointerSize, rcx);
Index: src/x64/lithium-x64.cc
diff --git a/src/x64/lithium-x64.cc b/src/x64/lithium-x64.cc
index 574970c6994e701cab44a590ac58d0f6aa121479..11c8a32d2693d6f28ad39271c84eb9715e20c48e 100644
--- a/src/x64/lithium-x64.cc
+++ b/src/x64/lithium-x64.cc
@@ -1006,7 +1006,14 @@ LInstruction* LChunkBuilder::DoThisFunction(HThisFunction* instr) {


 LInstruction* LChunkBuilder::DoContext(HContext* instr) {
- return instr->HasNoUses() ? NULL : DefineAsRegister(new(zone()) LContext); + // If there is a non-return use, the context must be allocated in a register.
+  for (HUseIterator it(instr->uses()); !it.Done(); it.Advance()) {
+    if (!it.value()->IsReturn()) {
+      return DefineAsRegister(new(zone()) LContext);
+    }
+  }
+
+  return NULL;
 }




--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev

Reply via email to