Revision: 7083
Author: [email protected]
Date: Mon Mar 7 11:23:46 2011
Log: Strict mode arguments do not share binding with formal parameters.
Move strict mode flag from TemporaryScope to Scope so that it can be
accessed from variable binding code.
Arguments do not alias in strict mode (ia32, x64 and arm, codegen and full
codegen).
Hydrogen tolerates null arguments_shadow().
In codegen-<arch> arguments object is allocated eagerly to capture values
before they get modified.
Review URL: http://codereview.chromium.org/6625048/
http://code.google.com/p/v8/source/detail?r=7083
Modified:
/branches/bleeding_edge/src/arm/codegen-arm.cc
/branches/bleeding_edge/src/arm/full-codegen-arm.cc
/branches/bleeding_edge/src/ast-inl.h
/branches/bleeding_edge/src/ast.h
/branches/bleeding_edge/src/hydrogen.cc
/branches/bleeding_edge/src/ia32/codegen-ia32.cc
/branches/bleeding_edge/src/ia32/full-codegen-ia32.cc
/branches/bleeding_edge/src/parser.cc
/branches/bleeding_edge/src/scopes.cc
/branches/bleeding_edge/src/scopes.h
/branches/bleeding_edge/src/x64/codegen-x64.cc
/branches/bleeding_edge/src/x64/full-codegen-x64.cc
/branches/bleeding_edge/test/es5conform/es5conform.status
/branches/bleeding_edge/test/mjsunit/strict-mode.js
=======================================
--- /branches/bleeding_edge/src/arm/codegen-arm.cc Wed Mar 2 06:40:38 2011
+++ /branches/bleeding_edge/src/arm/codegen-arm.cc Mon Mar 7 11:23:46 2011
@@ -577,11 +577,13 @@
ArgumentsAllocationMode CodeGenerator::ArgumentsMode() {
if (scope()->arguments() == NULL) return NO_ARGUMENTS_ALLOCATION;
- ASSERT(scope()->arguments_shadow() != NULL);
+
+ // In strict mode there is no need for shadow arguments.
+ ASSERT(scope()->arguments_shadow() != NULL || scope()->is_strict_mode());
// We don't want to do lazy arguments allocation for functions that
// have heap-allocated contexts, because it interfers with the
// uninitialized const tracking in the context objects.
- return (scope()->num_heap_slots() > 0)
+ return (scope()->num_heap_slots() > 0 || scope()->is_strict_mode())
? EAGER_ARGUMENTS_ALLOCATION
: LAZY_ARGUMENTS_ALLOCATION;
}
@@ -615,7 +617,9 @@
Variable* arguments = scope()->arguments();
Variable* shadow = scope()->arguments_shadow();
ASSERT(arguments != NULL && arguments->AsSlot() != NULL);
- ASSERT(shadow != NULL && shadow->AsSlot() != NULL);
+ ASSERT((shadow != NULL && shadow->AsSlot() != NULL) ||
+ scope()->is_strict_mode());
+
JumpTarget done;
if (mode == LAZY_ARGUMENTS_ALLOCATION && !initial) {
// We have to skip storing into the arguments slot if it has
@@ -629,7 +633,9 @@
}
StoreToSlot(arguments->AsSlot(), NOT_CONST_INIT);
if (mode == LAZY_ARGUMENTS_ALLOCATION) done.Bind();
- StoreToSlot(shadow->AsSlot(), NOT_CONST_INIT);
+ if (shadow != NULL) {
+ StoreToSlot(shadow->AsSlot(), NOT_CONST_INIT);
+ }
}
=======================================
--- /branches/bleeding_edge/src/arm/full-codegen-arm.cc Thu Mar 3 04:16:21
2011
+++ /branches/bleeding_edge/src/arm/full-codegen-arm.cc Mon Mar 7 11:23:46
2011
@@ -212,11 +212,14 @@
// stack frame was an arguments adapter frame.
ArgumentsAccessStub stub(ArgumentsAccessStub::NEW_OBJECT);
__ CallStub(&stub);
- // Duplicate the value; move-to-slot operation might clobber registers.
- __ mov(r3, r0);
+
+ Variable* arguments_shadow = scope()->arguments_shadow();
+ if (arguments_shadow != NULL) {
+ // Duplicate the value; move-to-slot operation might clobber
registers.
+ __ mov(r3, r0);
+ Move(arguments_shadow->AsSlot(), r3, r1, r2);
+ }
Move(arguments->AsSlot(), r0, r1, r2);
- Slot* dot_arguments_slot = scope()->arguments_shadow()->AsSlot();
- Move(dot_arguments_slot, r3, r1, r2);
}
if (FLAG_trace) {
=======================================
--- /branches/bleeding_edge/src/ast-inl.h Thu Dec 16 05:13:36 2010
+++ /branches/bleeding_edge/src/ast-inl.h Mon Mar 7 11:23:46 2011
@@ -100,6 +100,11 @@
: IterationStatement(labels), each_(NULL), enumerable_(NULL),
assignment_id_(GetNextId()) {
}
+
+
+bool FunctionLiteral::strict_mode() const {
+ return scope()->is_strict_mode();
+}
} } // namespace v8::internal
=======================================
--- /branches/bleeding_edge/src/ast.h Thu Jan 27 06:04:07 2011
+++ /branches/bleeding_edge/src/ast.h Mon Mar 7 11:23:46 2011
@@ -1673,8 +1673,7 @@
int start_position,
int end_position,
bool is_expression,
- bool contains_loops,
- bool strict_mode)
+ bool contains_loops)
: name_(name),
scope_(scope),
body_(body),
@@ -1688,7 +1687,6 @@
end_position_(end_position),
is_expression_(is_expression),
contains_loops_(contains_loops),
- strict_mode_(strict_mode),
function_token_position_(RelocInfo::kNoPosition),
inferred_name_(Heap::empty_string()),
try_full_codegen_(false),
@@ -1705,7 +1703,7 @@
int end_position() const { return end_position_; }
bool is_expression() const { return is_expression_; }
bool contains_loops() const { return contains_loops_; }
- bool strict_mode() const { return strict_mode_; }
+ bool strict_mode() const;
int materialized_literal_count() { return materialized_literal_count_; }
int expected_property_count() { return expected_property_count_; }
=======================================
--- /branches/bleeding_edge/src/hydrogen.cc Mon Mar 7 09:01:12 2011
+++ /branches/bleeding_edge/src/hydrogen.cc Mon Mar 7 11:23:46 2011
@@ -2292,14 +2292,17 @@
// not have declarations).
if (scope->arguments() != NULL) {
if (!scope->arguments()->IsStackAllocated() ||
- !scope->arguments_shadow()->IsStackAllocated()) {
+ (scope->arguments_shadow() != NULL &&
+ !scope->arguments_shadow()->IsStackAllocated())) {
BAILOUT("context-allocated arguments");
}
HArgumentsObject* object = new HArgumentsObject;
AddInstruction(object);
graph()->SetArgumentsObject(object);
environment()->Bind(scope->arguments(), object);
- environment()->Bind(scope->arguments_shadow(), object);
+ if (scope->arguments_shadow() != NULL) {
+ environment()->Bind(scope->arguments_shadow(), object);
+ }
}
}
=======================================
--- /branches/bleeding_edge/src/ia32/codegen-ia32.cc Tue Mar 1 20:53:43
2011
+++ /branches/bleeding_edge/src/ia32/codegen-ia32.cc Mon Mar 7 11:23:46
2011
@@ -729,11 +729,14 @@
ArgumentsAllocationMode CodeGenerator::ArgumentsMode() {
if (scope()->arguments() == NULL) return NO_ARGUMENTS_ALLOCATION;
- ASSERT(scope()->arguments_shadow() != NULL);
+
+ // In strict mode there is no need for shadow arguments.
+ ASSERT(scope()->arguments_shadow() != NULL || scope()->is_strict_mode());
+
// We don't want to do lazy arguments allocation for functions that
// have heap-allocated contexts, because it interfers with the
// uninitialized const tracking in the context objects.
- return (scope()->num_heap_slots() > 0)
+ return (scope()->num_heap_slots() > 0 || scope()->is_strict_mode())
? EAGER_ARGUMENTS_ALLOCATION
: LAZY_ARGUMENTS_ALLOCATION;
}
@@ -760,8 +763,11 @@
Variable* arguments = scope()->arguments();
Variable* shadow = scope()->arguments_shadow();
+
ASSERT(arguments != NULL && arguments->AsSlot() != NULL);
- ASSERT(shadow != NULL && shadow->AsSlot() != NULL);
+ ASSERT((shadow != NULL && shadow->AsSlot() != NULL) ||
+ scope()->is_strict_mode());
+
JumpTarget done;
bool skip_arguments = false;
if (mode == LAZY_ARGUMENTS_ALLOCATION && !initial) {
@@ -784,7 +790,9 @@
StoreToSlot(arguments->AsSlot(), NOT_CONST_INIT);
if (mode == LAZY_ARGUMENTS_ALLOCATION) done.Bind();
}
- StoreToSlot(shadow->AsSlot(), NOT_CONST_INIT);
+ if (shadow != NULL) {
+ StoreToSlot(shadow->AsSlot(), NOT_CONST_INIT);
+ }
return frame_->Pop();
}
=======================================
--- /branches/bleeding_edge/src/ia32/full-codegen-ia32.cc Thu Mar 3
04:16:21 2011
+++ /branches/bleeding_edge/src/ia32/full-codegen-ia32.cc Mon Mar 7
11:23:46 2011
@@ -199,10 +199,13 @@
// stack frame was an arguments adapter frame.
ArgumentsAccessStub stub(ArgumentsAccessStub::NEW_OBJECT);
__ CallStub(&stub);
- __ mov(ecx, eax); // Duplicate result.
+
+ Variable* arguments_shadow = scope()->arguments_shadow();
+ if (arguments_shadow != NULL) {
+ __ mov(ecx, eax); // Duplicate result.
+ Move(arguments_shadow->AsSlot(), ecx, ebx, edx);
+ }
Move(arguments->AsSlot(), eax, ebx, edx);
- Slot* dot_arguments_slot = scope()->arguments_shadow()->AsSlot();
- Move(dot_arguments_slot, ecx, ebx, edx);
}
if (FLAG_trace) {
=======================================
--- /branches/bleeding_edge/src/parser.cc Thu Mar 3 16:21:52 2011
+++ /branches/bleeding_edge/src/parser.cc Mon Mar 7 11:23:46 2011
@@ -282,11 +282,6 @@
void AddLoop() { loop_count_++; }
bool ContainsLoops() const { return loop_count_ > 0; }
-
- bool StrictMode() { return strict_mode_; }
- void EnableStrictMode() {
- strict_mode_ = FLAG_strict_mode;
- }
private:
// Captures the number of literals that need materialization in the
@@ -305,9 +300,6 @@
// Captures the number of loops inside the scope.
int loop_count_;
- // Parsing strict mode code.
- bool strict_mode_;
-
// Bookkeeping
TemporaryScope** variable_;
TemporaryScope* parent_;
@@ -322,8 +314,6 @@
loop_count_(0),
variable_(variable),
parent_(*variable) {
- // Inherit the strict mode from the parent scope.
- strict_mode_ = (parent_ != NULL) && parent_->strict_mode_;
*variable = this;
}
@@ -665,13 +655,13 @@
scope);
TemporaryScope temp_scope(&this->temp_scope_);
if (strict_mode == kStrictMode) {
- temp_scope.EnableStrictMode();
+ top_scope_->EnableStrictMode();
}
ZoneList<Statement*>* body = new ZoneList<Statement*>(16);
bool ok = true;
int beg_loc = scanner().location().beg_pos;
ParseSourceElements(body, Token::EOS, &ok);
- if (ok && temp_scope_->StrictMode()) {
+ if (ok && top_scope_->is_strict_mode()) {
CheckOctalLiteral(beg_loc, scanner().location().end_pos, &ok);
}
if (ok) {
@@ -687,8 +677,7 @@
0,
source->length(),
false,
- temp_scope.ContainsLoops(),
- temp_scope.StrictMode());
+ temp_scope.ContainsLoops());
} else if (stack_overflow_) {
Top::StackOverflow();
}
@@ -753,7 +742,7 @@
TemporaryScope temp_scope(&this->temp_scope_);
if (info->strict_mode()) {
- temp_scope.EnableStrictMode();
+ top_scope_->EnableStrictMode();
}
FunctionLiteralType type =
@@ -1140,11 +1129,11 @@
Handle<String> directive = Handle<String>::cast(literal->handle());
// Check "use strict" directive (ES5 14.1).
- if (!temp_scope_->StrictMode() &&
+ if (!top_scope_->is_strict_mode() &&
directive->Equals(Heap::use_strict()) &&
token_loc.end_pos - token_loc.beg_pos ==
Heap::use_strict()->length() + 2) {
- temp_scope_->EnableStrictMode();
+ top_scope_->EnableStrictMode();
// "use strict" is the only directive for now.
directive_prologue = false;
}
@@ -1282,7 +1271,7 @@
case Token::FUNCTION: {
// In strict mode, FunctionDeclaration is only allowed in the context
// of SourceElements.
- if (temp_scope_->StrictMode()) {
+ if (top_scope_->is_strict_mode()) {
ReportMessageAt(scanner().peek_location(), "strict_function",
Vector<const char*>::empty());
*ok = false;
@@ -1540,7 +1529,7 @@
Consume(Token::VAR);
} else if (peek() == Token::CONST) {
Consume(Token::CONST);
- if (temp_scope_->StrictMode()) {
+ if (top_scope_->is_strict_mode()) {
ReportMessage("strict_const", Vector<const char*>::empty());
*ok = false;
return NULL;
@@ -1576,7 +1565,7 @@
if (fni_ != NULL) fni_->PushVariableName(name);
// Strict mode variables may not be named eval or arguments
- if (temp_scope_->StrictMode() && IsEvalOrArguments(name)) {
+ if (top_scope_->is_strict_mode() && IsEvalOrArguments(name)) {
ReportMessage("strict_var_name", Vector<const char*>::empty());
*ok = false;
return NULL;
@@ -1685,7 +1674,7 @@
// Add strict mode.
// We may want to pass singleton to avoid Literal allocations.
arguments->Add(NewNumberLiteral(
- temp_scope_->StrictMode() ? kStrictMode : kNonStrictMode));
+ top_scope_->is_strict_mode() ? kStrictMode : kNonStrictMode));
// Be careful not to assign a value to the global variable if
// we're in a with. The initialization value should not
@@ -1958,7 +1947,7 @@
Expect(Token::WITH, CHECK_OK);
- if (temp_scope_->StrictMode()) {
+ if (top_scope_->is_strict_mode()) {
ReportMessage("strict_mode_with", Vector<const char*>::empty());
*ok = false;
return NULL;
@@ -2097,7 +2086,7 @@
Expect(Token::LPAREN, CHECK_OK);
Handle<String> name = ParseIdentifier(CHECK_OK);
- if (temp_scope_->StrictMode() && IsEvalOrArguments(name)) {
+ if (top_scope_->is_strict_mode() && IsEvalOrArguments(name)) {
ReportMessage("strict_catch_variable", Vector<const char*>::empty());
*ok = false;
return NULL;
@@ -2348,7 +2337,7 @@
expression = NewThrowReferenceError(type);
}
- if (temp_scope_->StrictMode()) {
+ if (top_scope_->is_strict_mode()) {
// Assignment to eval or arguments is disallowed in strict mode.
CheckStrictModeLValue(expression, "strict_lhs_assignment", CHECK_OK);
}
@@ -2567,7 +2556,7 @@
}
// "delete identifier" is a syntax error in strict mode.
- if (op == Token::DELETE && temp_scope_->StrictMode()) {
+ if (op == Token::DELETE && top_scope_->is_strict_mode()) {
VariableProxy* operand = expression->AsVariableProxy();
if (operand != NULL && !operand->is_this()) {
ReportMessage("strict_delete", Vector<const char*>::empty());
@@ -2590,7 +2579,7 @@
expression = NewThrowReferenceError(type);
}
- if (temp_scope_->StrictMode()) {
+ if (top_scope_->is_strict_mode()) {
// Prefix expression operand in strict mode may not be eval or
arguments.
CheckStrictModeLValue(expression, "strict_lhs_prefix", CHECK_OK);
}
@@ -2621,7 +2610,7 @@
expression = NewThrowReferenceError(type);
}
- if (temp_scope_->StrictMode()) {
+ if (top_scope_->is_strict_mode()) {
// Postfix expression operand in strict mode may not be eval or
arguments.
CheckStrictModeLValue(expression, "strict_lhs_prefix", CHECK_OK);
}
@@ -2829,7 +2818,7 @@
return ReportMessage("unexpected_token_identifier",
Vector<const char*>::empty());
case Token::FUTURE_RESERVED_WORD:
- return ReportMessage(temp_scope_->StrictMode() ?
+ return ReportMessage(top_scope_->is_strict_mode() ?
"unexpected_strict_reserved" :
"unexpected_token_identifier",
Vector<const char*>::empty());
@@ -3334,7 +3323,7 @@
new ZoneList<ObjectLiteral::Property*>(4);
int number_of_boilerplate_properties = 0;
- ObjectLiteralPropertyChecker checker(this, temp_scope_->StrictMode());
+ ObjectLiteralPropertyChecker checker(this, top_scope_->is_strict_mode());
Expect(Token::LBRACE, CHECK_OK);
Scanner::Location loc = scanner().location();
@@ -3631,7 +3620,7 @@
}
// Validate strict mode.
- if (temp_scope_->StrictMode()) {
+ if (top_scope_->is_strict_mode()) {
if (IsEvalOrArguments(name)) {
int position = function_token_position != RelocInfo::kNoPosition
? function_token_position
@@ -3685,8 +3674,7 @@
start_pos,
end_pos,
function_name->length() > 0,
- temp_scope.ContainsLoops(),
- temp_scope.StrictMode());
+ temp_scope.ContainsLoops());
function_literal->set_function_token_position(function_token_position);
if (fni_ != NULL && !is_named) fni_->AddFunction(function_literal);
@@ -3815,7 +3803,7 @@
Handle<String> Parser::ParseIdentifierOrReservedWord(bool* is_reserved,
bool* ok) {
*is_reserved = false;
- if (temp_scope_->StrictMode()) {
+ if (top_scope_->is_strict_mode()) {
Expect(Token::IDENTIFIER, ok);
} else {
if (!Check(Token::IDENTIFIER)) {
@@ -3846,7 +3834,7 @@
void Parser::CheckStrictModeLValue(Expression* expression,
const char* error,
bool* ok) {
- ASSERT(temp_scope_->StrictMode());
+ ASSERT(top_scope_->is_strict_mode());
VariableProxy* lhs = expression != NULL
? expression->AsVariableProxy()
: NULL;
=======================================
--- /branches/bleeding_edge/src/scopes.cc Mon Feb 7 01:55:42 2011
+++ /branches/bleeding_edge/src/scopes.cc Mon Mar 7 11:23:46 2011
@@ -878,6 +878,11 @@
ASSERT(is_function_scope());
Variable* arguments = LocalLookup(Factory::arguments_symbol());
ASSERT(arguments != NULL); // functions have 'arguments' declared
implicitly
+
+ // Parameters are rewritten to arguments[i] if 'arguments' is used in
+ // a non-strict mode function. Strict mode code doesn't alias arguments.
+ bool rewrite_parameters = false;
+
if (MustAllocate(arguments) && !HasArgumentsParameter()) {
// 'arguments' is used. Unless there is also a parameter called
// 'arguments', we must be conservative and access all parameters via
@@ -909,6 +914,13 @@
// allocate the arguments object by setting 'arguments_'.
arguments_ = arguments;
+ // In strict mode 'arguments' does not alias formal parameters.
+ // Therefore in strict mode we allocate parameters as if 'arguments'
+ // were not used.
+ rewrite_parameters = !is_strict_mode();
+ }
+
+ if (rewrite_parameters) {
// We also need the '.arguments' shadow variable. Declare it and create
// and bind the corresponding proxy. It's ok to declare it only now
// because it's a local variable that is allocated after the parameters
=======================================
--- /branches/bleeding_edge/src/scopes.h Tue Jan 25 09:21:45 2011
+++ /branches/bleeding_edge/src/scopes.h Mon Mar 7 11:23:46 2011
@@ -193,6 +193,10 @@
// Inform the scope that the corresponding code contains an eval call.
void RecordEvalCall() { scope_calls_eval_ = true; }
+ // Enable strict mode for the scope (unless disabled by a global flag).
+ void EnableStrictMode() {
+ strict_mode_ = FLAG_strict_mode;
+ }
//
---------------------------------------------------------------------------
// Predicates.
@@ -201,6 +205,7 @@
bool is_eval_scope() const { return type_ == EVAL_SCOPE; }
bool is_function_scope() const { return type_ == FUNCTION_SCOPE; }
bool is_global_scope() const { return type_ == GLOBAL_SCOPE; }
+ bool is_strict_mode() const { return strict_mode_; }
// Information about which scopes calls eval.
bool calls_eval() const { return scope_calls_eval_; }
@@ -363,6 +368,7 @@
bool scope_inside_with_; // this scope is inside a 'with' of some outer
scope
bool scope_contains_with_; // this scope contains a 'with' statement
bool scope_calls_eval_; // this scope contains an 'eval' call
+ bool strict_mode_; // this scope is a strict mode scope
// Computed via PropagateScopeInfo.
bool outer_scope_calls_eval_;
@@ -428,6 +434,8 @@
scope_inside_with_ = false;
scope_contains_with_ = false;
scope_calls_eval_ = false;
+ // Inherit the strict mode from the parent scope.
+ strict_mode_ = (outer_scope != NULL) && outer_scope->strict_mode_;
outer_scope_calls_eval_ = false;
inner_scope_calls_eval_ = false;
outer_scope_is_eval_scope_ = false;
=======================================
--- /branches/bleeding_edge/src/x64/codegen-x64.cc Mon Mar 7 00:35:19 2011
+++ /branches/bleeding_edge/src/x64/codegen-x64.cc Mon Mar 7 11:23:46 2011
@@ -611,11 +611,13 @@
ArgumentsAllocationMode CodeGenerator::ArgumentsMode() {
if (scope()->arguments() == NULL) return NO_ARGUMENTS_ALLOCATION;
- ASSERT(scope()->arguments_shadow() != NULL);
+
+ // In strict mode there is no need for shadow arguments.
+ ASSERT(scope()->arguments_shadow() != NULL || scope()->is_strict_mode());
// We don't want to do lazy arguments allocation for functions that
// have heap-allocated contexts, because it interfers with the
// uninitialized const tracking in the context objects.
- return (scope()->num_heap_slots() > 0)
+ return (scope()->num_heap_slots() > 0 || scope()->is_strict_mode())
? EAGER_ARGUMENTS_ALLOCATION
: LAZY_ARGUMENTS_ALLOCATION;
}
@@ -643,7 +645,9 @@
Variable* arguments = scope()->arguments();
Variable* shadow = scope()->arguments_shadow();
ASSERT(arguments != NULL && arguments->AsSlot() != NULL);
- ASSERT(shadow != NULL && shadow->AsSlot() != NULL);
+ ASSERT((shadow != NULL && shadow->AsSlot() != NULL) ||
+ scope()->is_strict_mode());
+
JumpTarget done;
bool skip_arguments = false;
if (mode == LAZY_ARGUMENTS_ALLOCATION && !initial) {
@@ -666,7 +670,9 @@
StoreToSlot(arguments->AsSlot(), NOT_CONST_INIT);
if (mode == LAZY_ARGUMENTS_ALLOCATION) done.Bind();
}
- StoreToSlot(shadow->AsSlot(), NOT_CONST_INIT);
+ if (shadow != NULL) {
+ StoreToSlot(shadow->AsSlot(), NOT_CONST_INIT);
+ }
return frame_->Pop();
}
=======================================
--- /branches/bleeding_edge/src/x64/full-codegen-x64.cc Thu Mar 3 04:16:21
2011
+++ /branches/bleeding_edge/src/x64/full-codegen-x64.cc Mon Mar 7 11:23:46
2011
@@ -200,11 +200,14 @@
// stack frame was an arguments adapter frame.
ArgumentsAccessStub stub(ArgumentsAccessStub::NEW_OBJECT);
__ CallStub(&stub);
- // Store new arguments object in both "arguments" and ".arguments"
slots.
- __ movq(rcx, rax);
+
+ Variable* arguments_shadow = scope()->arguments_shadow();
+ if (arguments_shadow != NULL) {
+ // Store new arguments object in both "arguments" and ".arguments"
slots.
+ __ movq(rcx, rax);
+ Move(arguments_shadow->AsSlot(), rcx, rbx, rdx);
+ }
Move(arguments->AsSlot(), rax, rbx, rdx);
- Slot* dot_arguments_slot = scope()->arguments_shadow()->AsSlot();
- Move(dot_arguments_slot, rcx, rbx, rdx);
}
if (FLAG_trace) {
=======================================
--- /branches/bleeding_edge/test/es5conform/es5conform.status Tue Mar 1
20:53:43 2011
+++ /branches/bleeding_edge/test/es5conform/es5conform.status Mon Mar 7
11:23:46 2011
@@ -239,11 +239,6 @@
# Incorrect test - need double escape in eval.
chapter07/7.8/7.8.4/7.8.4-1-s: FAIL
-# arguments[i] remains same after changing actual parameters in strict mode
-chapter10/10.6/10.6-10-c-ii-1-s: FAIL
-# arguments[i] doesn't map to actual parameters in strict mode
-chapter10/10.6/10.6-10-c-ii-2-s: FAIL
-
# Accessing caller property of Arguments object throws TypeError in strict
mode
chapter10/10.6/10.6-13-b-1-s: FAIL
# arguments.caller exists in strict mode
=======================================
--- /branches/bleeding_edge/test/mjsunit/strict-mode.js Fri Mar 4 13:12:29
2011
+++ /branches/bleeding_edge/test/mjsunit/strict-mode.js Mon Mar 7 11:23:46
2011
@@ -957,3 +957,22 @@
assertThrows(function() { str_obj.length = 1; }, TypeError);
assertThrows(function() { str_cat.length = 1; }, TypeError);
})();
+
+
+(function TestArgumentsAliasing() {
+ function strict(a, b) {
+ "use strict";
+ a = "c";
+ b = "d";
+ return [a, b, arguments[0], arguments[1]];
+ }
+
+ function nonstrict(a, b) {
+ a = "c";
+ b = "d";
+ return [a, b, arguments[0], arguments[1]];
+ }
+
+ assertEquals(["c", "d", "a", "b"], strict("a", "b"));
+ assertEquals(["c", "d", "c", "d"], nonstrict("a", "b"));
+})();
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev