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:
parent
bea46a2723
commit
2e08148b06
@ -3053,26 +3053,30 @@ void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
|
||||
// Result of deleting non-global, non-dynamic variables is false.
|
||||
// The subexpression does not have side effects.
|
||||
context()->Plug(false);
|
||||
} else if (prop != NULL) {
|
||||
if (prop->is_synthetic()) {
|
||||
// Result of deleting parameters is false, even when they rewrite
|
||||
// to accesses on the arguments object.
|
||||
context()->Plug(false);
|
||||
} else {
|
||||
// Property or variable reference. Call the delete builtin with
|
||||
// object and property name as arguments.
|
||||
if (prop != NULL) {
|
||||
VisitForStackValue(prop->obj());
|
||||
VisitForStackValue(prop->key());
|
||||
__ InvokeBuiltin(Builtins::DELETE, CALL_JS);
|
||||
context()->Plug(r0);
|
||||
}
|
||||
} 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 delete from the
|
||||
// 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);
|
||||
}
|
||||
break;
|
||||
|
@ -4653,12 +4653,18 @@ void HGraphBuilder::VisitUnaryOperation(UnaryOperation* expr) {
|
||||
// The subexpression does not have side effects.
|
||||
ast_context()->ReturnValue(graph()->GetConstantFalse());
|
||||
} else if (prop != NULL) {
|
||||
if (prop->is_synthetic()) {
|
||||
// Result of deleting parameters is false, even when they rewrite
|
||||
// to accesses on the arguments object.
|
||||
ast_context()->ReturnValue(graph()->GetConstantFalse());
|
||||
} else {
|
||||
VISIT_FOR_VALUE(prop->obj());
|
||||
VISIT_FOR_VALUE(prop->key());
|
||||
HValue* key = Pop();
|
||||
HValue* obj = Pop();
|
||||
ast_context()->ReturnInstruction(new HDeleteProperty(obj, key),
|
||||
expr->id());
|
||||
HDeleteProperty* instr = new HDeleteProperty(obj, key);
|
||||
ast_context()->ReturnInstruction(instr, expr->id());
|
||||
}
|
||||
} else if (var->is_global()) {
|
||||
BAILOUT("delete with global variable");
|
||||
} else {
|
||||
|
@ -3721,24 +3721,28 @@ void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
|
||||
// Result of deleting non-global, non-dynamic variables is false.
|
||||
// The subexpression does not have side effects.
|
||||
context()->Plug(false);
|
||||
} else if (prop != NULL) {
|
||||
if (prop->is_synthetic()) {
|
||||
// Result of deleting parameters is false, even when they rewrite
|
||||
// to accesses on the arguments object.
|
||||
context()->Plug(false);
|
||||
} else {
|
||||
// Property or variable reference. Call the delete builtin with
|
||||
// object and property name as arguments.
|
||||
if (prop != NULL) {
|
||||
VisitForStackValue(prop->obj());
|
||||
VisitForStackValue(prop->key());
|
||||
__ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION);
|
||||
context()->Plug(eax);
|
||||
}
|
||||
} 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 delete from the
|
||||
// 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);
|
||||
}
|
||||
break;
|
||||
|
@ -3060,24 +3060,28 @@ void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
|
||||
// Result of deleting non-global, non-dynamic variables is false.
|
||||
// The subexpression does not have side effects.
|
||||
context()->Plug(false);
|
||||
} else if (prop != NULL) {
|
||||
if (prop->is_synthetic()) {
|
||||
// Result of deleting parameters is false, even when they rewrite
|
||||
// to accesses on the arguments object.
|
||||
context()->Plug(false);
|
||||
} else {
|
||||
// Property or variable reference. Call the delete builtin with
|
||||
// object and property name as arguments.
|
||||
if (prop != NULL) {
|
||||
VisitForStackValue(prop->obj());
|
||||
VisitForStackValue(prop->key());
|
||||
__ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION);
|
||||
context()->Plug(rax);
|
||||
}
|
||||
} 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 delete from the
|
||||
// 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);
|
||||
}
|
||||
break;
|
||||
|
Loading…
Reference in New Issue
Block a user