Revision: 6426
Author: [email protected]
Date: Fri Jan 21 03:28:35 2011
Log: 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.
Review URL: http://codereview.chromium.org/6248014
http://code.google.com/p/v8/source/detail?r=6426
Modified:
/branches/bleeding_edge/src/arm/code-stubs-arm.cc
/branches/bleeding_edge/src/arm/codegen-arm.cc
/branches/bleeding_edge/src/arm/full-codegen-arm.cc
/branches/bleeding_edge/src/code-stubs.h
/branches/bleeding_edge/src/ia32/code-stubs-ia32.cc
/branches/bleeding_edge/src/ia32/codegen-ia32.cc
/branches/bleeding_edge/src/ia32/full-codegen-ia32.cc
/branches/bleeding_edge/src/scopes.cc
/branches/bleeding_edge/src/x64/code-stubs-x64.cc
/branches/bleeding_edge/src/x64/codegen-x64.cc
/branches/bleeding_edge/src/x64/full-codegen-x64.cc
/branches/bleeding_edge/test/mjsunit/debug-evaluate-locals.js
=======================================
--- /branches/bleeding_edge/src/arm/code-stubs-arm.cc Wed Jan 19 06:53:38
2011
+++ /branches/bleeding_edge/src/arm/code-stubs-arm.cc Fri Jan 21 03:28:35
2011
@@ -112,10 +112,9 @@
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 @@
// 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 @@
// 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)));
}
=======================================
--- /branches/bleeding_edge/src/arm/codegen-arm.cc Tue Jan 11 04:45:25 2011
+++ /branches/bleeding_edge/src/arm/codegen-arm.cc Fri Jan 21 03:28:35 2011
@@ -209,7 +209,7 @@
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.
=======================================
--- /branches/bleeding_edge/src/arm/full-codegen-arm.cc Wed Jan 19 07:26:54
2011
+++ /branches/bleeding_edge/src/arm/full-codegen-arm.cc Fri Jan 21 03:28:35
2011
@@ -92,7 +92,7 @@
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.
=======================================
--- /branches/bleeding_edge/src/code-stubs.h Fri Jan 7 02:37:26 2011
+++ /branches/bleeding_edge/src/code-stubs.h Fri Jan 21 03:28:35 2011
@@ -273,20 +273,21 @@
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_;
-
- const char* GetName() { return "FastNewContextStub"; }
- Major MajorKey() { return FastNewContext; }
- int MinorKey() { return slots_; }
+ virtual const char* GetName() { return "FastNewContextStub"; }
+ virtual Major MajorKey() { return FastNewContext; }
+ virtual int MinorKey() { return slots_; }
+
+ int slots_;
};
=======================================
--- /branches/bleeding_edge/src/ia32/code-stubs-ia32.cc Thu Jan 13 00:24:19
2011
+++ /branches/bleeding_edge/src/ia32/code-stubs-ia32.cc Fri Jan 21 03:28:35
2011
@@ -91,8 +91,7 @@
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 @@
// 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 @@
// 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);
}
=======================================
--- /branches/bleeding_edge/src/ia32/codegen-ia32.cc Fri Jan 14 02:57:49
2011
+++ /branches/bleeding_edge/src/ia32/codegen-ia32.cc Fri Jan 21 03:28:35
2011
@@ -209,7 +209,7 @@
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.
=======================================
--- /branches/bleeding_edge/src/ia32/full-codegen-ia32.cc Wed Jan 19
07:26:54 2011
+++ /branches/bleeding_edge/src/ia32/full-codegen-ia32.cc Fri Jan 21
03:28:35 2011
@@ -142,7 +142,7 @@
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.
=======================================
--- /branches/bleeding_edge/src/scopes.cc Thu Jan 20 04:58:57 2011
+++ /branches/bleeding_edge/src/scopes.cc Fri Jan 21 03:28:35 2011
@@ -726,6 +726,7 @@
// 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 @@
// 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.
=======================================
--- /branches/bleeding_edge/src/x64/code-stubs-x64.cc Wed Jan 19 02:17:18
2011
+++ /branches/bleeding_edge/src/x64/code-stubs-x64.cc Fri Jan 21 03:28:35
2011
@@ -91,8 +91,7 @@
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 @@
// 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 @@
// 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);
}
=======================================
--- /branches/bleeding_edge/src/x64/codegen-x64.cc Thu Jan 6 07:53:56 2011
+++ /branches/bleeding_edge/src/x64/codegen-x64.cc Fri Jan 21 03:28:35 2011
@@ -206,7 +206,7 @@
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.
=======================================
--- /branches/bleeding_edge/src/x64/full-codegen-x64.cc Wed Jan 19 07:26:54
2011
+++ /branches/bleeding_edge/src/x64/full-codegen-x64.cc Fri Jan 21 03:28:35
2011
@@ -88,7 +88,7 @@
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.
=======================================
--- /branches/bleeding_edge/test/mjsunit/debug-evaluate-locals.js Thu Jan
20 04:58:57 2011
+++ /branches/bleeding_edge/test/mjsunit/debug-evaluate-locals.js Fri Jan
21 03:28:35 2011
@@ -34,18 +34,18 @@
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 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 @@
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());
-
- // Frame 2 has normal variables a and b (and both the .arguments and
- // arguments variable).
+ checkFrame1(frame1.localName(2), frame1.localValue(2).value());
+
+ // 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