Fix the semantics of delete on parameters.

Before, an attempt to delete a parameter in a function that used the
arguments object in any way would succeed with true and delete both
the parameter and the corresponding arguments object property.

Now, an attempt to delete such a parameter does not delete and
evaluates to false.

Parameters can be deleted, as before, from functions that use the
arguments object, by deleting the corresponding arguments object
property (this is a spec violation).

BUG=fixes v8:1136

Review URL: http://codereview.chromium.org/6484023

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@6745 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
kmillikin@chromium.org 2011-02-11 11:57:11 +00:00
parent bea46a2723
commit 2e08148b06
4 changed files with 68 additions and 50 deletions

View File

@ -3053,26 +3053,30 @@ void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
// Result of deleting non-global, non-dynamic variables is false. // Result of deleting non-global, non-dynamic variables is false.
// The subexpression does not have side effects. // The subexpression does not have side effects.
context()->Plug(false); context()->Plug(false);
} else { } else if (prop != NULL) {
// Property or variable reference. Call the delete builtin with if (prop->is_synthetic()) {
// object and property name as arguments. // Result of deleting parameters is false, even when they rewrite
if (prop != NULL) { // to accesses on the arguments object.
context()->Plug(false);
} else {
VisitForStackValue(prop->obj()); VisitForStackValue(prop->obj());
VisitForStackValue(prop->key()); VisitForStackValue(prop->key());
__ InvokeBuiltin(Builtins::DELETE, CALL_JS); __ InvokeBuiltin(Builtins::DELETE, CALL_JS);
} else if (var->is_global()) { context()->Plug(r0);
__ ldr(r1, GlobalObjectOperand());
__ mov(r0, Operand(var->name()));
__ Push(r1, r0);
__ InvokeBuiltin(Builtins::DELETE, CALL_JS);
} else {
// Non-global variable. Call the runtime to delete from the
// context where the variable was introduced.
__ push(context_register());
__ mov(r2, Operand(var->name()));
__ push(r2);
__ CallRuntime(Runtime::kDeleteContextSlot, 2);
} }
} else if (var->is_global()) {
__ ldr(r1, GlobalObjectOperand());
__ mov(r0, Operand(var->name()));
__ Push(r1, r0);
__ InvokeBuiltin(Builtins::DELETE, CALL_JS);
context()->Plug(r0);
} else {
// Non-global variable. Call the runtime to try to delete from the
// context where the variable was introduced.
__ push(context_register());
__ mov(r2, Operand(var->name()));
__ push(r2);
__ CallRuntime(Runtime::kDeleteContextSlot, 2);
context()->Plug(r0); context()->Plug(r0);
} }
break; break;

View File

@ -4653,12 +4653,18 @@ void HGraphBuilder::VisitUnaryOperation(UnaryOperation* expr) {
// The subexpression does not have side effects. // The subexpression does not have side effects.
ast_context()->ReturnValue(graph()->GetConstantFalse()); ast_context()->ReturnValue(graph()->GetConstantFalse());
} else if (prop != NULL) { } else if (prop != NULL) {
VISIT_FOR_VALUE(prop->obj()); if (prop->is_synthetic()) {
VISIT_FOR_VALUE(prop->key()); // Result of deleting parameters is false, even when they rewrite
HValue* key = Pop(); // to accesses on the arguments object.
HValue* obj = Pop(); ast_context()->ReturnValue(graph()->GetConstantFalse());
ast_context()->ReturnInstruction(new HDeleteProperty(obj, key), } else {
expr->id()); VISIT_FOR_VALUE(prop->obj());
VISIT_FOR_VALUE(prop->key());
HValue* key = Pop();
HValue* obj = Pop();
HDeleteProperty* instr = new HDeleteProperty(obj, key);
ast_context()->ReturnInstruction(instr, expr->id());
}
} else if (var->is_global()) { } else if (var->is_global()) {
BAILOUT("delete with global variable"); BAILOUT("delete with global variable");
} else { } else {

View File

@ -3721,24 +3721,28 @@ void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
// Result of deleting non-global, non-dynamic variables is false. // Result of deleting non-global, non-dynamic variables is false.
// The subexpression does not have side effects. // The subexpression does not have side effects.
context()->Plug(false); context()->Plug(false);
} else { } else if (prop != NULL) {
// Property or variable reference. Call the delete builtin with if (prop->is_synthetic()) {
// object and property name as arguments. // Result of deleting parameters is false, even when they rewrite
if (prop != NULL) { // to accesses on the arguments object.
context()->Plug(false);
} else {
VisitForStackValue(prop->obj()); VisitForStackValue(prop->obj());
VisitForStackValue(prop->key()); VisitForStackValue(prop->key());
__ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION); __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION);
} else if (var->is_global()) { context()->Plug(eax);
__ push(GlobalObjectOperand());
__ push(Immediate(var->name()));
__ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION);
} else {
// Non-global variable. Call the runtime to delete from the
// context where the variable was introduced.
__ push(context_register());
__ push(Immediate(var->name()));
__ CallRuntime(Runtime::kDeleteContextSlot, 2);
} }
} else if (var->is_global()) {
__ push(GlobalObjectOperand());
__ push(Immediate(var->name()));
__ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION);
context()->Plug(eax);
} else {
// Non-global variable. Call the runtime to try to delete from the
// context where the variable was introduced.
__ push(context_register());
__ push(Immediate(var->name()));
__ CallRuntime(Runtime::kDeleteContextSlot, 2);
context()->Plug(eax); context()->Plug(eax);
} }
break; break;

View File

@ -3060,24 +3060,28 @@ void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
// Result of deleting non-global, non-dynamic variables is false. // Result of deleting non-global, non-dynamic variables is false.
// The subexpression does not have side effects. // The subexpression does not have side effects.
context()->Plug(false); context()->Plug(false);
} else { } else if (prop != NULL) {
// Property or variable reference. Call the delete builtin with if (prop->is_synthetic()) {
// object and property name as arguments. // Result of deleting parameters is false, even when they rewrite
if (prop != NULL) { // to accesses on the arguments object.
context()->Plug(false);
} else {
VisitForStackValue(prop->obj()); VisitForStackValue(prop->obj());
VisitForStackValue(prop->key()); VisitForStackValue(prop->key());
__ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION); __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION);
} else if (var->is_global()) { context()->Plug(rax);
__ push(GlobalObjectOperand());
__ Push(var->name());
__ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION);
} else {
// Non-global variable. Call the runtime to delete from the
// context where the variable was introduced.
__ push(context_register());
__ Push(var->name());
__ CallRuntime(Runtime::kDeleteContextSlot, 2);
} }
} else if (var->is_global()) {
__ push(GlobalObjectOperand());
__ Push(var->name());
__ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION);
context()->Plug(rax);
} else {
// Non-global variable. Call the runtime to try to delete from the
// context where the variable was introduced.
__ push(context_register());
__ Push(var->name());
__ CallRuntime(Runtime::kDeleteContextSlot, 2);
context()->Plug(rax); context()->Plug(rax);
} }
break; break;