Reviewers: Mads Ager,

Message:
The bugfix I adopted was to make the FastNewContextStub include the number of context slots in its count so we didn't subtract in the code generator and add
back in the stub.

Description:
Reapply change to with/arguments interaction.

This is svn r6415 with a bugfix.

The bug was that we can have scopes with 0 heap slots (functions with
such scopes do not need a local context) and scopes with at least
Context::MIN_CONTEXT_SLOTS.  The code generator only allocated a local
context if there were strictly more than Context::MIN_CONTEXT_SLOTS.
Before the change to with/arguments, it was impossible to actually get
a function scope with exactly Context::MIN_CONTEXT_SLOTS because every
such scope included a heap-allocated arguments (and arguments shadow)
slot.

Please review this at http://codereview.chromium.org/6248014/

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

Affected files:
  M src/arm/code-stubs-arm.cc
  M src/arm/codegen-arm.cc
  M src/arm/full-codegen-arm.cc
  M src/code-stubs.h
  M src/ia32/code-stubs-ia32.cc
  M src/ia32/codegen-ia32.cc
  M src/ia32/full-codegen-ia32.cc
  M src/scopes.cc
  M src/x64/code-stubs-x64.cc
  M src/x64/codegen-x64.cc
  M src/x64/full-codegen-x64.cc
  M test/mjsunit/debug-evaluate-locals.js


Index: src/arm/code-stubs-arm.cc
diff --git a/src/arm/code-stubs-arm.cc b/src/arm/code-stubs-arm.cc
index bf7ac5fb827709e620a38f3ca4c02e274bdc14fc..a44600727579043f89852f211f7d61ef3838c3e2 100644
--- a/src/arm/code-stubs-arm.cc
+++ b/src/arm/code-stubs-arm.cc
@@ -112,10 +112,9 @@ void FastNewClosureStub::Generate(MacroAssembler* masm) {
 void FastNewContextStub::Generate(MacroAssembler* masm) {
   // Try to allocate the context in new space.
   Label gc;
-  int length = slots_ + Context::MIN_CONTEXT_SLOTS;

   // Attempt to allocate the context in new space.
-  __ AllocateInNewSpace(FixedArray::SizeFor(length),
+  __ AllocateInNewSpace(FixedArray::SizeFor(slots_),
                         r0,
                         r1,
                         r2,
@@ -128,7 +127,7 @@ void FastNewContextStub::Generate(MacroAssembler* masm) {
   // Setup the object header.
   __ LoadRoot(r2, Heap::kContextMapRootIndex);
   __ str(r2, FieldMemOperand(r0, HeapObject::kMapOffset));
-  __ mov(r2, Operand(Smi::FromInt(length)));
+  __ mov(r2, Operand(Smi::FromInt(slots_)));
   __ str(r2, FieldMemOperand(r0, FixedArray::kLengthOffset));

   // Setup the fixed slots.
@@ -144,7 +143,7 @@ void FastNewContextStub::Generate(MacroAssembler* masm) {

   // Initialize the rest of the slots to undefined.
   __ LoadRoot(r1, Heap::kUndefinedValueRootIndex);
-  for (int i = Context::MIN_CONTEXT_SLOTS; i < length; i++) {
+  for (int i = Context::MIN_CONTEXT_SLOTS; i < slots_; i++) {
     __ str(r1, MemOperand(r0, Context::SlotOffset(i)));
   }

Index: src/arm/codegen-arm.cc
diff --git a/src/arm/codegen-arm.cc b/src/arm/codegen-arm.cc
index 4a982f6e5c53062e9125b264519eefed4799fae6..2fa071195953fa7b28aaa86734012455d5d68541 100644
--- a/src/arm/codegen-arm.cc
+++ b/src/arm/codegen-arm.cc
@@ -209,7 +209,7 @@ void CodeGenerator::Generate(CompilationInfo* info) {
     frame_->AllocateStackSlots();

     frame_->AssertIsSpilled();
- int heap_slots = scope()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS;
+    int heap_slots = scope()->num_heap_slots();
     if (heap_slots > 0) {
       // Allocate local context.
       // Get outer context and create a new context based on it.
Index: src/arm/full-codegen-arm.cc
diff --git a/src/arm/full-codegen-arm.cc b/src/arm/full-codegen-arm.cc
index d8ca130da44442a962364e2fac3d80b2a5bf7b56..ddc74e2f734b1b67056a54e26e4f2b92dd157ca1 100644
--- a/src/arm/full-codegen-arm.cc
+++ b/src/arm/full-codegen-arm.cc
@@ -92,7 +92,7 @@ void FullCodeGenerator::Generate(CompilationInfo* info) {
   bool function_in_register = true;

   // Possibly allocate a local context.
-  int heap_slots = scope()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS;
+  int heap_slots = scope()->num_heap_slots();
   if (heap_slots > 0) {
     Comment cmnt(masm_, "[ Allocate local context");
     // Argument to NewContext is the function, which is in r1.
Index: src/code-stubs.h
diff --git a/src/code-stubs.h b/src/code-stubs.h
index 76f29f082f44b92aee35334a53a80b5edcbf12e3..bc7516a3fe3e6a18e54f68b5dacd81be250567d8 100644
--- a/src/code-stubs.h
+++ b/src/code-stubs.h
@@ -273,20 +273,21 @@ class FastNewClosureStub : public CodeStub {

 class FastNewContextStub : public CodeStub {
  public:
-  static const int kMaximumSlots = 64;
+  // We want no more than 64 different stubs.
+  static const int kMaximumSlots = Context::MIN_CONTEXT_SLOTS + 63;

   explicit FastNewContextStub(int slots) : slots_(slots) {
-    ASSERT(slots_ > 0 && slots <= kMaximumSlots);
+ ASSERT(slots_ >= Context::MIN_CONTEXT_SLOTS && slots_ <= kMaximumSlots);
   }

   void Generate(MacroAssembler* masm);

  private:
-  int slots_;
+  virtual const char* GetName() { return "FastNewContextStub"; }
+  virtual Major MajorKey() { return FastNewContext; }
+  virtual int MinorKey() { return slots_; }

-  const char* GetName() { return "FastNewContextStub"; }
-  Major MajorKey() { return FastNewContext; }
-  int MinorKey() { return slots_; }
+  int slots_;
 };


Index: src/ia32/code-stubs-ia32.cc
diff --git a/src/ia32/code-stubs-ia32.cc b/src/ia32/code-stubs-ia32.cc
index 72213dc817487e15e50cf35fb790d3bf7e84db82..2c83662efd3853cafeac85d23da62fd5cf8d441e 100644
--- a/src/ia32/code-stubs-ia32.cc
+++ b/src/ia32/code-stubs-ia32.cc
@@ -91,8 +91,7 @@ void FastNewClosureStub::Generate(MacroAssembler* masm) {
 void FastNewContextStub::Generate(MacroAssembler* masm) {
   // Try to allocate the context in new space.
   Label gc;
-  int length = slots_ + Context::MIN_CONTEXT_SLOTS;
-  __ AllocateInNewSpace((length * kPointerSize) + FixedArray::kHeaderSize,
+  __ AllocateInNewSpace((slots_ * kPointerSize) + FixedArray::kHeaderSize,
                         eax, ebx, ecx, &gc, TAG_OBJECT);

   // Get the function from the stack.
@@ -101,7 +100,7 @@ void FastNewContextStub::Generate(MacroAssembler* masm) {
   // Setup the object header.
__ mov(FieldOperand(eax, HeapObject::kMapOffset), Factory::context_map());
   __ mov(FieldOperand(eax, Context::kLengthOffset),
-         Immediate(Smi::FromInt(length)));
+         Immediate(Smi::FromInt(slots_)));

   // Setup the fixed slots.
   __ Set(ebx, Immediate(0));  // Set to NULL.
@@ -119,7 +118,7 @@ void FastNewContextStub::Generate(MacroAssembler* masm) {

   // Initialize the rest of the slots to undefined.
   __ mov(ebx, Factory::undefined_value());
-  for (int i = Context::MIN_CONTEXT_SLOTS; i < length; i++) {
+  for (int i = Context::MIN_CONTEXT_SLOTS; i < slots_; i++) {
     __ mov(Operand(eax, Context::SlotOffset(i)), ebx);
   }

Index: src/ia32/codegen-ia32.cc
diff --git a/src/ia32/codegen-ia32.cc b/src/ia32/codegen-ia32.cc
index 1ecfd39ca1edc5864e090a49b253a9f01aea210c..29c8c0e406cf927e2071f00071ac7e31403d9a02 100644
--- a/src/ia32/codegen-ia32.cc
+++ b/src/ia32/codegen-ia32.cc
@@ -209,7 +209,7 @@ void CodeGenerator::Generate(CompilationInfo* info) {
     frame_->AllocateStackSlots();

     // Allocate the local context if needed.
- int heap_slots = scope()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS;
+    int heap_slots = scope()->num_heap_slots();
     if (heap_slots > 0) {
       Comment cmnt(masm_, "[ allocate local context");
       // Allocate local context.
Index: src/ia32/full-codegen-ia32.cc
diff --git a/src/ia32/full-codegen-ia32.cc b/src/ia32/full-codegen-ia32.cc
index ea947eedaf940009e375493c78b6ecfc30511859..772eb8f9054c3121447068516d23ba7915f98c94 100644
--- a/src/ia32/full-codegen-ia32.cc
+++ b/src/ia32/full-codegen-ia32.cc
@@ -142,7 +142,7 @@ void FullCodeGenerator::Generate(CompilationInfo* info) {
   bool function_in_register = true;

   // Possibly allocate a local context.
-  int heap_slots = scope()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS;
+  int heap_slots = scope()->num_heap_slots();
   if (heap_slots > 0) {
     Comment cmnt(masm_, "[ Allocate local context");
     // Argument to NewContext is the function, which is still in edi.
Index: src/scopes.cc
diff --git a/src/scopes.cc b/src/scopes.cc
index d3f54ad3f2d9ad8b47fefae2d89fd692bd3e2eda..50da1faf913cc391ad07f2d672d94e1e2fc241eb 100644
--- a/src/scopes.cc
+++ b/src/scopes.cc
@@ -726,6 +726,7 @@ void Scope::ResolveVariable(Scope* global_scope,
     // Note that we must do a lookup anyway, because if we find one,
     // we must mark that variable as potentially accessed from this
     // inner scope (the property may not be in the 'with' object).
+    if (var != NULL) var->set_is_used(true);
     var = NonLocal(proxy->name(), Variable::DYNAMIC);

   } else {
@@ -833,8 +834,8 @@ bool Scope::MustAllocate(Variable* var) {
   // visible name.
   if ((var->is_this() || var->name()->length() > 0) &&
       (var->is_accessed_from_inner_scope() ||
-       scope_calls_eval_ || inner_scope_calls_eval_ ||
-       scope_contains_with_)) {
+       scope_calls_eval_ ||
+       inner_scope_calls_eval_)) {
     var->set_is_used(true);
   }
   // Global variables do not need to be allocated.
Index: src/x64/code-stubs-x64.cc
diff --git a/src/x64/code-stubs-x64.cc b/src/x64/code-stubs-x64.cc
index d121dfb1c493d90eafd7e737cc969ccbff0668fe..a261b9d086d24219ef62ec92a4522a4ecd3ef8bd 100644
--- a/src/x64/code-stubs-x64.cc
+++ b/src/x64/code-stubs-x64.cc
@@ -91,8 +91,7 @@ void FastNewClosureStub::Generate(MacroAssembler* masm) {
 void FastNewContextStub::Generate(MacroAssembler* masm) {
   // Try to allocate the context in new space.
   Label gc;
-  int length = slots_ + Context::MIN_CONTEXT_SLOTS;
-  __ AllocateInNewSpace((length * kPointerSize) + FixedArray::kHeaderSize,
+  __ AllocateInNewSpace((slots_ * kPointerSize) + FixedArray::kHeaderSize,
                         rax, rbx, rcx, &gc, TAG_OBJECT);

   // Get the function from the stack.
@@ -101,7 +100,7 @@ void FastNewContextStub::Generate(MacroAssembler* masm) {
   // Setup the object header.
   __ LoadRoot(kScratchRegister, Heap::kContextMapRootIndex);
   __ movq(FieldOperand(rax, HeapObject::kMapOffset), kScratchRegister);
- __ Move(FieldOperand(rax, FixedArray::kLengthOffset), Smi::FromInt(length)); + __ Move(FieldOperand(rax, FixedArray::kLengthOffset), Smi::FromInt(slots_));

   // Setup the fixed slots.
   __ Set(rbx, 0);  // Set to NULL.
@@ -116,7 +115,7 @@ void FastNewContextStub::Generate(MacroAssembler* masm) {

   // Initialize the rest of the slots to undefined.
   __ LoadRoot(rbx, Heap::kUndefinedValueRootIndex);
-  for (int i = Context::MIN_CONTEXT_SLOTS; i < length; i++) {
+  for (int i = Context::MIN_CONTEXT_SLOTS; i < slots_; i++) {
     __ movq(Operand(rax, Context::SlotOffset(i)), rbx);
   }

Index: src/x64/codegen-x64.cc
diff --git a/src/x64/codegen-x64.cc b/src/x64/codegen-x64.cc
index a543a504871054b9020e7c0496a6a8a5db88c511..57720a8019b362eb03c12747dc2182c91cec0d4f 100644
--- a/src/x64/codegen-x64.cc
+++ b/src/x64/codegen-x64.cc
@@ -206,7 +206,7 @@ void CodeGenerator::Generate(CompilationInfo* info) {
     frame_->AllocateStackSlots();

     // Allocate the local context if needed.
- int heap_slots = scope()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS;
+    int heap_slots = scope()->num_heap_slots();
     if (heap_slots > 0) {
       Comment cmnt(masm_, "[ allocate local context");
       // Allocate local context.
Index: src/x64/full-codegen-x64.cc
diff --git a/src/x64/full-codegen-x64.cc b/src/x64/full-codegen-x64.cc
index b6e81b0f14a47b2ccd515bc889cb026c3db317bb..896e53da60425c5641f12977e69f3cc9ed1a7d92 100644
--- a/src/x64/full-codegen-x64.cc
+++ b/src/x64/full-codegen-x64.cc
@@ -88,7 +88,7 @@ void FullCodeGenerator::Generate(CompilationInfo* info) {
   bool function_in_register = true;

   // Possibly allocate a local context.
-  int heap_slots = scope()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS;
+  int heap_slots = scope()->num_heap_slots();
   if (heap_slots > 0) {
     Comment cmnt(masm_, "[ Allocate local context");
     // Argument to NewContext is the function, which is still in rdi.
Index: test/mjsunit/debug-evaluate-locals.js
diff --git a/test/mjsunit/debug-evaluate-locals.js b/test/mjsunit/debug-evaluate-locals.js index 4b87829169586ed4885bee9236138ecbd51faa87..8430bd3576e7465541fba241e2a76ba657cbf5fa 100644
--- a/test/mjsunit/debug-evaluate-locals.js
+++ b/test/mjsunit/debug-evaluate-locals.js
@@ -34,18 +34,18 @@ exception = false;


 function checkFrame0(name, value) {
-  assertTrue(name == 'a' || name == 'b');
+  assertTrue(name == 'a' || name == 'b', 'frame0 name');
   if (name == 'a') {
     assertEquals(1, value);
-  }
-  if (name == 'b') {
+  } else if (name == 'b') {
     assertEquals(2, value);
   }
 }


 function checkFrame1(name, value) {
-  assertTrue(name == '.arguments' || name == 'a');
+  assertTrue(name == '.arguments' || name == 'arguments' || name == 'a',
+             'frame1 name');
   if (name == 'a') {
     assertEquals(3, value);
   }
@@ -53,12 +53,10 @@ function checkFrame1(name, value) {


 function checkFrame2(name, value) {
-  assertTrue(name == '.arguments' || name == 'a' ||
-             name == 'arguments' || name == 'b');
+  assertTrue(name == 'a' || name == 'b', 'frame2 name');
   if (name == 'a') {
     assertEquals(5, value);
-  }
-  if (name == 'b') {
+  } else if (name == 'b') {
     assertEquals(0, value);
   }
 }
@@ -73,18 +71,17 @@ function listener(event, exec_state, event_data, data) {
       checkFrame0(frame0.localName(0), frame0.localValue(0).value());
       checkFrame0(frame0.localName(1), frame0.localValue(1).value());

-      // Frame 1 has normal variable a (and the .arguments variable).
+      // Frame 1 has normal variables a and arguments (and the .arguments
+      // variable).
       var frame1 = exec_state.frame(1);
       checkFrame1(frame1.localName(0), frame1.localValue(0).value());
       checkFrame1(frame1.localName(1), frame1.localValue(1).value());
+      checkFrame1(frame1.localName(2), frame1.localValue(2).value());

-      // Frame 2 has normal variables a and b (and both the .arguments and
-      // arguments variable).
+      // Frame 2 has normal variables a and b.
       var frame2 = exec_state.frame(2);
       checkFrame2(frame2.localName(0), frame2.localValue(0).value());
       checkFrame2(frame2.localName(1), frame2.localValue(1).value());
-      checkFrame2(frame2.localName(2), frame2.localValue(2).value());
-      checkFrame2(frame2.localName(3), frame2.localValue(3).value());

// Evaluating a and b on frames 0, 1 and 2 produces 1, 2, 3, 4, 5 and 6.
       assertEquals(1, exec_state.frame(0).evaluate('a').value());


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

Reply via email to