void ValueContext::ReturnValue(HValue* value) {
// The value is tracked in the bailout environment, and communicated
// through the environment as the result of the expression.
+ if (!arguments_allowed() && value->CheckFlag(HValue::kIsArguments)) {
+ owner()->Bailout("bad value context for arguments value");
+ }
owner()->Push(value);
}
void ValueContext::ReturnInstruction(HInstruction* instr, int ast_id) {
+ if (!arguments_allowed() && instr->CheckFlag(HValue::kIsArguments)) {
+ owner()->Bailout("bad value context for arguments object value");
+ }
owner()->AddInstruction(instr);
owner()->Push(instr);
if (instr->HasSideEffects()) owner()->AddSimulate(ast_id);
// property by always adding an empty block on the outgoing edges of this
// branch.
HGraphBuilder* builder = owner();
+ if (value->CheckFlag(HValue::kIsArguments)) {
+ builder->Bailout("arguments object value in a test context");
+ }
HBasicBlock* empty_true = builder->graph()->CreateBasicBlock();
HBasicBlock* empty_false = builder->graph()->CreateBasicBlock();
HTest* test = new(zone()) HTest(value, empty_true, empty_false);
}
-void HGraphBuilder::VisitForValue(Expression* expr) {
- ValueContext for_value(this);
+void HGraphBuilder::VisitForValue(Expression* expr, ArgumentsAllowedFlag flag) {
+ ValueContext for_value(this, flag);
Visit(expr);
}
void HGraphBuilder::VisitForTypeOf(Expression* expr) {
- ValueContext for_value(this);
+ ValueContext for_value(this, ARGUMENTS_NOT_ALLOWED);
for_value.set_for_typeof(true);
Visit(expr);
}
if (variable == NULL) {
return Bailout("reference to rewritten variable");
} else if (variable->IsStackAllocated()) {
- if (environment()->Lookup(variable)->CheckFlag(HValue::kIsArguments)) {
- return Bailout("unsupported context for arguments object");
- }
ast_context()->ReturnValue(environment()->Lookup(variable));
} else if (variable->IsContextSlot()) {
if (variable->mode() == Variable::CONST) {
// Handle the assignment.
if (var->IsStackAllocated()) {
- HValue* value = NULL;
- // Handle stack-allocated variables on the right-hand side directly.
// We do not allow the arguments object to occur in a context where it
// may escape, but assignments to stack-allocated locals are
- // permitted. Handling such assignments here bypasses the check for
- // the arguments object in VisitVariableProxy.
- Variable* rhs_var = expr->value()->AsVariableProxy()->AsVariable();
- if (rhs_var != NULL && rhs_var->IsStackAllocated()) {
- value = environment()->Lookup(rhs_var);
- } else {
- CHECK_ALIVE(VisitForValue(expr->value()));
- value = Pop();
- }
+ // permitted.
+ CHECK_ALIVE(VisitForValue(expr->value(), ARGUMENTS_ALLOWED));
+ HValue* value = Pop();
Bind(var, value);
ast_context()->ReturnValue(value);
class HGraphBuilder;
+enum ArgumentsAllowedFlag {
+ ARGUMENTS_NOT_ALLOWED,
+ ARGUMENTS_ALLOWED
+};
+
// This class is not BASE_EMBEDDED because our inlining implementation uses
// new and delete.
class AstContext {
class ValueContext: public AstContext {
public:
- explicit ValueContext(HGraphBuilder* owner)
- : AstContext(owner, Expression::kValue) {
+ explicit ValueContext(HGraphBuilder* owner, ArgumentsAllowedFlag flag)
+ : AstContext(owner, Expression::kValue), flag_(flag) {
}
virtual ~ValueContext();
virtual void ReturnValue(HValue* value);
virtual void ReturnInstruction(HInstruction* instr, int ast_id);
+
+ bool arguments_allowed() { return flag_ == ARGUMENTS_ALLOWED; }
+
+ private:
+ ArgumentsAllowedFlag flag_;
};
void Push(HValue* value) { environment()->Push(value); }
HValue* Pop() { return environment()->Pop(); }
+ void Bailout(const char* reason);
+
private:
// Type of a member function that generates inline code for a native function.
typedef void (HGraphBuilder::*InlineFunctionGenerator)(CallRuntime* call);
INLINE_RUNTIME_FUNCTION_LIST(INLINE_FUNCTION_GENERATOR_DECLARATION)
#undef INLINE_FUNCTION_GENERATOR_DECLARATION
- void Bailout(const char* reason);
-
void PreProcessOsrEntry(IterationStatement* statement);
// True iff. we are compiling for OSR and the statement is the entry.
bool HasOsrEntryAt(IterationStatement* statement);
void Drop(int n) { environment()->Drop(n); }
void Bind(Variable* var, HValue* value) { environment()->Bind(var, value); }
- void VisitForValue(Expression* expr);
+ // The value of the arguments object is allowed in some but not most value
+ // contexts. (It's allowed in all effect contexts and disallowed in all
+ // test contexts.)
+ void VisitForValue(Expression* expr,
+ ArgumentsAllowedFlag flag = ARGUMENTS_NOT_ALLOWED);
void VisitForTypeOf(Expression* expr);
void VisitForEffect(Expression* expr);
void VisitForControl(Expression* expr,
--- /dev/null
+// Copyright 2011 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Flags: --allow-natives-syntax
+
+// Test that the arguments value is does not escape when it appears as
+// an intermediate value in an expression.
+
+function h() { }
+
+function f() {
+ var a = null;
+ h(a = arguments);
+}
+
+f();
+%OptimizeFunctionOnNextCall(f);
+f();