Revision: 2984 Author: [email protected] Date: Tue Sep 29 06:28:30 2009 Log: Remove CallEval as a subclass of the Call AST node type. We were not differentiating between Call and CallEval except in the code generator, and the difference can be detected from a regular Call AST node at code generation time.
Review URL: http://codereview.chromium.org/245042 http://code.google.com/p/v8/source/detail?r=2984 Modified: /branches/bleeding_edge/src/arm/codegen-arm.cc /branches/bleeding_edge/src/ast.cc /branches/bleeding_edge/src/ast.h /branches/bleeding_edge/src/cfg.cc /branches/bleeding_edge/src/ia32/codegen-ia32.cc /branches/bleeding_edge/src/parser.cc /branches/bleeding_edge/src/prettyprinter.cc /branches/bleeding_edge/src/rewriter.cc /branches/bleeding_edge/src/usage-analyzer.cc /branches/bleeding_edge/src/variables.h /branches/bleeding_edge/src/x64/codegen-x64.cc ======================================= --- /branches/bleeding_edge/src/arm/codegen-arm.cc Mon Sep 28 05:01:05 2009 +++ /branches/bleeding_edge/src/arm/codegen-arm.cc Tue Sep 29 06:28:30 2009 @@ -2907,11 +2907,11 @@ VirtualFrame::SpilledScope spilled_scope; Comment cmnt(masm_, "[ Call"); + Expression* function = node->expression(); ZoneList<Expression*>* args = node->arguments(); // Standard function call. // Check if the function is a variable or a property. - Expression* function = node->expression(); Variable* var = function->AsVariableProxy()->AsVariable(); Property* property = function->AsProperty(); @@ -2924,8 +2924,57 @@ // is resolved in cache misses (this also holds for megamorphic calls). // ------------------------------------------------------------------------ - if (var != NULL && !var->is_this() && var->is_global()) { + if (var != NULL && var->is_possibly_eval()) { // ---------------------------------- + // JavaScript example: 'eval(arg)' // eval is not known to be shadowed + // ---------------------------------- + + // In a call to eval, we first call %ResolvePossiblyDirectEval to + // resolve the function we need to call and the receiver of the + // call. Then we call the resolved function using the given + // arguments. + // Prepare stack for call to resolved function. + LoadAndSpill(function); + __ LoadRoot(r2, Heap::kUndefinedValueRootIndex); + frame_->EmitPush(r2); // Slot for receiver + int arg_count = args->length(); + for (int i = 0; i < arg_count; i++) { + LoadAndSpill(args->at(i)); + } + + // Prepare stack for call to ResolvePossiblyDirectEval. + __ ldr(r1, MemOperand(sp, arg_count * kPointerSize + kPointerSize)); + frame_->EmitPush(r1); + if (arg_count > 0) { + __ ldr(r1, MemOperand(sp, arg_count * kPointerSize)); + frame_->EmitPush(r1); + } else { + frame_->EmitPush(r2); + } + + // Resolve the call. + frame_->CallRuntime(Runtime::kResolvePossiblyDirectEval, 2); + + // Touch up stack with the right values for the function and the receiver. + __ ldr(r1, FieldMemOperand(r0, FixedArray::kHeaderSize)); + __ str(r1, MemOperand(sp, (arg_count + 1) * kPointerSize)); + __ ldr(r1, FieldMemOperand(r0, FixedArray::kHeaderSize + kPointerSize)); + __ str(r1, MemOperand(sp, arg_count * kPointerSize)); + + // Call the function. + CodeForSourcePosition(node->position()); + + InLoopFlag in_loop = loop_nesting() > 0 ? IN_LOOP : NOT_IN_LOOP; + CallFunctionStub call_function(arg_count, in_loop); + frame_->CallStub(&call_function, arg_count + 1); + + __ ldr(cp, frame_->Context()); + // Remove the function from the stack. + frame_->Drop(); + frame_->EmitPush(r0); + + } else if (var != NULL && !var->is_this() && var->is_global()) { + // ---------------------------------- // JavaScript example: 'foo(1, 2, 3)' // foo is global // ---------------------------------- @@ -3047,63 +3096,6 @@ } ASSERT(frame_->height() == original_height + 1); } - - -void CodeGenerator::VisitCallEval(CallEval* node) { -#ifdef DEBUG - int original_height = frame_->height(); -#endif - VirtualFrame::SpilledScope spilled_scope; - Comment cmnt(masm_, "[ CallEval"); - - // In a call to eval, we first call %ResolvePossiblyDirectEval to resolve - // the function we need to call and the receiver of the call. - // Then we call the resolved function using the given arguments. - - ZoneList<Expression*>* args = node->arguments(); - Expression* function = node->expression(); - - // Prepare stack for call to resolved function. - LoadAndSpill(function); - __ LoadRoot(r2, Heap::kUndefinedValueRootIndex); - frame_->EmitPush(r2); // Slot for receiver - int arg_count = args->length(); - for (int i = 0; i < arg_count; i++) { - LoadAndSpill(args->at(i)); - } - - // Prepare stack for call to ResolvePossiblyDirectEval. - __ ldr(r1, MemOperand(sp, arg_count * kPointerSize + kPointerSize)); - frame_->EmitPush(r1); - if (arg_count > 0) { - __ ldr(r1, MemOperand(sp, arg_count * kPointerSize)); - frame_->EmitPush(r1); - } else { - frame_->EmitPush(r2); - } - - // Resolve the call. - frame_->CallRuntime(Runtime::kResolvePossiblyDirectEval, 2); - - // Touch up stack with the right values for the function and the receiver. - __ ldr(r1, FieldMemOperand(r0, FixedArray::kHeaderSize)); - __ str(r1, MemOperand(sp, (arg_count + 1) * kPointerSize)); - __ ldr(r1, FieldMemOperand(r0, FixedArray::kHeaderSize + kPointerSize)); - __ str(r1, MemOperand(sp, arg_count * kPointerSize)); - - // Call the function. - CodeForSourcePosition(node->position()); - - InLoopFlag in_loop = loop_nesting() > 0 ? IN_LOOP : NOT_IN_LOOP; - CallFunctionStub call_function(arg_count, in_loop); - frame_->CallStub(&call_function, arg_count + 1); - - __ ldr(cp, frame_->Context()); - // Remove the function from the stack. - frame_->Drop(); - frame_->EmitPush(r0); - ASSERT(frame_->height() == original_height + 1); -} void CodeGenerator::VisitCallNew(CallNew* node) { ======================================= --- /branches/bleeding_edge/src/ast.cc Thu Jul 30 05:09:05 2009 +++ /branches/bleeding_edge/src/ast.cc Tue Sep 29 06:28:30 2009 @@ -40,7 +40,6 @@ ValidLeftHandSideSentinel ValidLeftHandSideSentinel::instance_; Property Property::this_property_(VariableProxySentinel::this_proxy(), NULL, 0); Call Call::sentinel_(NULL, NULL, 0); -CallEval CallEval::sentinel_(NULL, NULL, 0); // ---------------------------------------------------------------------------- ======================================= --- /branches/bleeding_edge/src/ast.h Mon Sep 28 05:01:05 2009 +++ /branches/bleeding_edge/src/ast.h Tue Sep 29 06:28:30 2009 @@ -85,7 +85,6 @@ V(Throw) \ V(Property) \ V(Call) \ - V(CallEval) \ V(CallNew) \ V(CallRuntime) \ V(UnaryOperation) \ @@ -991,24 +990,6 @@ }; -// The CallEval class represents a call of the form 'eval(...)' where eval -// cannot be seen to be overwritten at compile time. It is potentially a -// direct (i.e. not aliased) eval call. The real nature of the call is -// determined at runtime. -class CallEval: public Call { - public: - CallEval(Expression* expression, ZoneList<Expression*>* arguments, int pos) - : Call(expression, arguments, pos) { } - - virtual void Accept(AstVisitor* v); - - static CallEval* sentinel() { return &sentinel_; } - - private: - static CallEval sentinel_; -}; - - // The CallRuntime class does not represent any official JavaScript // language construct. Instead it is used to call a C or JS function // with a set of arguments. This is used from the builtins that are ======================================= --- /branches/bleeding_edge/src/cfg.cc Wed Sep 9 03:49:40 2009 +++ /branches/bleeding_edge/src/cfg.cc Tue Sep 29 06:28:30 2009 @@ -396,11 +396,6 @@ void ExpressionCfgBuilder::VisitCall(Call* expr) { BAILOUT("Call"); } - - -void ExpressionCfgBuilder::VisitCallEval(CallEval* expr) { - BAILOUT("CallEval"); -} void ExpressionCfgBuilder::VisitCallNew(CallNew* expr) { ======================================= --- /branches/bleeding_edge/src/ia32/codegen-ia32.cc Tue Sep 29 02:21:19 2009 +++ /branches/bleeding_edge/src/ia32/codegen-ia32.cc Tue Sep 29 06:28:30 2009 @@ -4431,10 +4431,10 @@ void CodeGenerator::VisitCall(Call* node) { Comment cmnt(masm_, "[ Call"); + Expression* function = node->expression(); ZoneList<Expression*>* args = node->arguments(); // Check if the function is a variable or a property. - Expression* function = node->expression(); Variable* var = function->AsVariableProxy()->AsVariable(); Property* property = function->AsProperty(); @@ -4447,8 +4447,64 @@ // is resolved in cache misses (this also holds for megamorphic calls). // ------------------------------------------------------------------------ - if (var != NULL && !var->is_this() && var->is_global()) { + if (var != NULL && var->is_possibly_eval()) { // ---------------------------------- + // JavaScript example: 'eval(arg)' // eval is not known to be shadowed + // ---------------------------------- + + // In a call to eval, we first call %ResolvePossiblyDirectEval to + // resolve the function we need to call and the receiver of the + // call. Then we call the resolved function using the given + // arguments. + + // Prepare the stack for the call to the resolved function. + Load(function); + + // Allocate a frame slot for the receiver. + frame_->Push(Factory::undefined_value()); + int arg_count = args->length(); + for (int i = 0; i < arg_count; i++) { + Load(args->at(i)); + } + + // Prepare the stack for the call to ResolvePossiblyDirectEval. + frame_->PushElementAt(arg_count + 1); + if (arg_count > 0) { + frame_->PushElementAt(arg_count); + } else { + frame_->Push(Factory::undefined_value()); + } + + // Resolve the call. + Result result = + frame_->CallRuntime(Runtime::kResolvePossiblyDirectEval, 2); + + // Touch up the stack with the right values for the function and the + // receiver. Use a scratch register to avoid destroying the result. + Result scratch = allocator_->Allocate(); + ASSERT(scratch.is_valid()); + __ mov(scratch.reg(), FieldOperand(result.reg(), FixedArray::kHeaderSize)); + frame_->SetElementAt(arg_count + 1, &scratch); + + // We can reuse the result register now. + frame_->Spill(result.reg()); + __ mov(result.reg(), + FieldOperand(result.reg(), FixedArray::kHeaderSize + kPointerSize)); + frame_->SetElementAt(arg_count, &result); + + // Call the function. + CodeForSourcePosition(node->position()); + InLoopFlag in_loop = loop_nesting() > 0 ? IN_LOOP : NOT_IN_LOOP; + CallFunctionStub call_function(arg_count, in_loop); + result = frame_->CallStub(&call_function, arg_count + 1); + + // Restore the context and overwrite the function on the stack with + // the result. + frame_->RestoreContextRegister(); + frame_->SetElementAt(0, &result); + + } else if (var != NULL && !var->is_this() && var->is_global()) { + // ---------------------------------- // JavaScript example: 'foo(1, 2, 3)' // foo is global // ---------------------------------- @@ -4614,64 +4670,6 @@ // Replace the function on the stack with the result. frame_->SetElementAt(0, &result); } - - -void CodeGenerator::VisitCallEval(CallEval* node) { - Comment cmnt(masm_, "[ CallEval"); - - // In a call to eval, we first call %ResolvePossiblyDirectEval to resolve - // the function we need to call and the receiver of the call. - // Then we call the resolved function using the given arguments. - - ZoneList<Expression*>* args = node->arguments(); - Expression* function = node->expression(); - - // Prepare the stack for the call to the resolved function. - Load(function); - - // Allocate a frame slot for the receiver. - frame_->Push(Factory::undefined_value()); - int arg_count = args->length(); - for (int i = 0; i < arg_count; i++) { - Load(args->at(i)); - } - - // Prepare the stack for the call to ResolvePossiblyDirectEval. - frame_->PushElementAt(arg_count + 1); - if (arg_count > 0) { - frame_->PushElementAt(arg_count); - } else { - frame_->Push(Factory::undefined_value()); - } - - // Resolve the call. - Result result = - frame_->CallRuntime(Runtime::kResolvePossiblyDirectEval, 2); - - // Touch up the stack with the right values for the function and the - // receiver. Use a scratch register to avoid destroying the result. - Result scratch = allocator_->Allocate(); - ASSERT(scratch.is_valid()); - __ mov(scratch.reg(), FieldOperand(result.reg(), FixedArray::kHeaderSize)); - frame_->SetElementAt(arg_count + 1, &scratch); - - // We can reuse the result register now. - frame_->Spill(result.reg()); - __ mov(result.reg(), - FieldOperand(result.reg(), FixedArray::kHeaderSize + kPointerSize)); - frame_->SetElementAt(arg_count, &result); - - // Call the function. - CodeForSourcePosition(node->position()); - InLoopFlag in_loop = loop_nesting() > 0 ? IN_LOOP : NOT_IN_LOOP; - CallFunctionStub call_function(arg_count, in_loop); - result = frame_->CallStub(&call_function, arg_count + 1); - - // Restore the context and overwrite the function on the stack with - // the result. - frame_->RestoreContextRegister(); - frame_->SetElementAt(0, &result); -} void CodeGenerator::GenerateIsSmi(ZoneList<Expression*>* args) { ======================================= --- /branches/bleeding_edge/src/parser.cc Mon Aug 31 08:02:54 2009 +++ /branches/bleeding_edge/src/parser.cc Tue Sep 29 06:28:30 2009 @@ -797,12 +797,6 @@ int pos) { return Call::sentinel(); } - - virtual Expression* NewCallEval(Expression* expression, - ZoneList<Expression*>* arguments, - int pos) { - return CallEval::sentinel(); - } virtual Statement* EmptyStatement() { return NULL; @@ -853,12 +847,6 @@ int pos) { return new Call(expression, arguments, pos); } - - virtual Expression* NewCallEval(Expression* expression, - ZoneList<Expression*>* arguments, - int pos) { - return new CallEval(expression, arguments, pos); - } virtual Statement* EmptyStatement(); }; @@ -3074,8 +3062,6 @@ // declared in the current scope chain. These calls are marked as // potentially direct eval calls. Whether they are actually direct calls // to eval is determined at run time. - - bool is_potentially_direct_eval = false; if (!is_pre_parsing_) { VariableProxy* callee = result->AsVariableProxy(); if (callee != NULL && callee->IsVariable(Factory::eval_symbol())) { @@ -3083,16 +3069,10 @@ Variable* var = top_scope_->Lookup(name); if (var == NULL) { top_scope_->RecordEvalCall(); - is_potentially_direct_eval = true; } } } - - if (is_potentially_direct_eval) { - result = factory()->NewCallEval(result, args, pos); - } else { - result = factory()->NewCall(result, args, pos); - } + result = factory()->NewCall(result, args, pos); break; } ======================================= --- /branches/bleeding_edge/src/prettyprinter.cc Thu Jul 30 04:53:29 2009 +++ /branches/bleeding_edge/src/prettyprinter.cc Tue Sep 29 06:28:30 2009 @@ -356,11 +356,6 @@ Visit(node->expression()); PrintArguments(node->arguments()); } - - -void PrettyPrinter::VisitCallEval(CallEval* node) { - VisitCall(node); -} void PrettyPrinter::VisitCallNew(CallNew* node) { @@ -1038,11 +1033,6 @@ Visit(node->expression()); PrintArguments(node->arguments()); } - - -void AstPrinter::VisitCallEval(CallEval* node) { - VisitCall(node); -} void AstPrinter::VisitCallNew(CallNew* node) { ======================================= --- /branches/bleeding_edge/src/rewriter.cc Thu Jul 30 05:09:05 2009 +++ /branches/bleeding_edge/src/rewriter.cc Tue Sep 29 06:28:30 2009 @@ -381,12 +381,6 @@ Visit(node->expression()); OptimizeArguments(node->arguments()); } - - -void AstOptimizer::VisitCallEval(CallEval* node) { - Visit(node->expression()); - OptimizeArguments(node->arguments()); -} void AstOptimizer::VisitCallNew(CallNew* node) { @@ -757,12 +751,6 @@ USE(node); UNREACHABLE(); } - - -void Processor::VisitCallEval(CallEval* node) { - USE(node); - UNREACHABLE(); -} void Processor::VisitCallNew(CallNew* node) { ======================================= --- /branches/bleeding_edge/src/usage-analyzer.cc Thu Jul 30 04:53:29 2009 +++ /branches/bleeding_edge/src/usage-analyzer.cc Tue Sep 29 06:28:30 2009 @@ -75,7 +75,6 @@ void VisitThrow(Throw* node); void VisitProperty(Property* node); void VisitCall(Call* node); - void VisitCallEval(CallEval* node); void VisitCallNew(CallNew* node); void VisitCallRuntime(CallRuntime* node); void VisitUnaryOperation(UnaryOperation* node); @@ -327,11 +326,6 @@ Read(node->expression()); ReadList(node->arguments()); } - - -void UsageComputer::VisitCallEval(CallEval* node) { - VisitCall(node); -} void UsageComputer::VisitCallNew(CallNew* node) { ======================================= --- /branches/bleeding_edge/src/variables.h Mon Aug 3 03:59:00 2009 +++ /branches/bleeding_edge/src/variables.h Tue Sep 29 06:28:30 2009 @@ -171,7 +171,7 @@ UseCount* var_uses() { return &var_uses_; } UseCount* obj_uses() { return &obj_uses_; } - bool IsVariable(Handle<String> n) { + bool IsVariable(Handle<String> n) const { return !is_this() && name().is_identical_to(n); } @@ -184,6 +184,12 @@ bool is_global() const; bool is_this() const { return kind_ == THIS; } bool is_arguments() const { return kind_ == ARGUMENTS; } + + // True if the variable is named eval and not known to be shadowed. + bool is_possibly_eval() const { + return IsVariable(Factory::eval_symbol()) && + (mode_ == DYNAMIC || mode_ == DYNAMIC_GLOBAL); + } Variable* local_if_not_shadowed() const { ASSERT(mode_ == DYNAMIC_LOCAL && local_if_not_shadowed_ != NULL); ======================================= --- /branches/bleeding_edge/src/x64/codegen-x64.cc Mon Sep 28 05:01:05 2009 +++ /branches/bleeding_edge/src/x64/codegen-x64.cc Tue Sep 29 06:28:30 2009 @@ -2704,8 +2704,65 @@ // is resolved in cache misses (this also holds for megamorphic calls). // ------------------------------------------------------------------------ - if (var != NULL && !var->is_this() && var->is_global()) { + if (var != NULL && var->is_possibly_eval()) { // ---------------------------------- + // JavaScript example: 'eval(arg)' // eval is not known to be shadowed + // ---------------------------------- + + // In a call to eval, we first call %ResolvePossiblyDirectEval to + // resolve the function we need to call and the receiver of the + // call. Then we call the resolved function using the given + // arguments. + + // Prepare the stack for the call to the resolved function. + Load(function); + + // Allocate a frame slot for the receiver. + frame_->Push(Factory::undefined_value()); + int arg_count = args->length(); + for (int i = 0; i < arg_count; i++) { + Load(args->at(i)); + } + + // Prepare the stack for the call to ResolvePossiblyDirectEval. + frame_->PushElementAt(arg_count + 1); + if (arg_count > 0) { + frame_->PushElementAt(arg_count); + } else { + frame_->Push(Factory::undefined_value()); + } + + // Resolve the call. + Result result = + frame_->CallRuntime(Runtime::kResolvePossiblyDirectEval, 2); + + // Touch up the stack with the right values for the function and the + // receiver. Use a scratch register to avoid destroying the result. + Result scratch = allocator_->Allocate(); + ASSERT(scratch.is_valid()); + __ movq(scratch.reg(), + FieldOperand(result.reg(), FixedArray::OffsetOfElementAt(0))); + frame_->SetElementAt(arg_count + 1, &scratch); + + // We can reuse the result register now. + frame_->Spill(result.reg()); + __ movq(result.reg(), + FieldOperand(result.reg(), FixedArray::OffsetOfElementAt(1))); + frame_->SetElementAt(arg_count, &result); + + // Call the function. + CodeForSourcePosition(node->position()); + InLoopFlag in_loop = loop_nesting() > 0 ? IN_LOOP : NOT_IN_LOOP; + CallFunctionStub call_function(arg_count, in_loop); + result = frame_->CallStub(&call_function, arg_count + 1); + + // Restore the context and overwrite the function on the stack with + // the result. + frame_->RestoreContextRegister(); + frame_->SetElementAt(0, &result); + + } else if (var != NULL && !var->is_this() && var->is_global()) { + // ---------------------------------- // JavaScript example: 'foo(1, 2, 3)' // foo is global // ---------------------------------- @@ -2731,6 +2788,7 @@ frame_->RestoreContextRegister(); // Replace the function on the stack with the result. frame_->SetElementAt(0, &result); + } else if (var != NULL && var->slot() != NULL && var->slot()->type() == Slot::LOOKUP) { // ---------------------------------- @@ -2757,6 +2815,7 @@ // Call the function. CallWithArguments(args, node->position()); + } else if (property != NULL) { // Check if the key is a literal string. Literal* literal = property->key()->AsLiteral(); @@ -2822,6 +2881,7 @@ // Call the function. CallWithArguments(args, node->position()); } + } else { // ---------------------------------- // JavaScript example: 'foo(1, 2, 3)' // foo is not global @@ -2837,65 +2897,6 @@ CallWithArguments(args, node->position()); } } - - -void CodeGenerator::VisitCallEval(CallEval* node) { - Comment cmnt(masm_, "[ CallEval"); - - // In a call to eval, we first call %ResolvePossiblyDirectEval to resolve - // the function we need to call and the receiver of the call. - // Then we call the resolved function using the given arguments. - - ZoneList<Expression*>* args = node->arguments(); - Expression* function = node->expression(); - - // Prepare the stack for the call to the resolved function. - Load(function); - - // Allocate a frame slot for the receiver. - frame_->Push(Factory::undefined_value()); - int arg_count = args->length(); - for (int i = 0; i < arg_count; i++) { - Load(args->at(i)); - } - - // Prepare the stack for the call to ResolvePossiblyDirectEval. - frame_->PushElementAt(arg_count + 1); - if (arg_count > 0) { - frame_->PushElementAt(arg_count); - } else { - frame_->Push(Factory::undefined_value()); - } - - // Resolve the call. - Result result = - frame_->CallRuntime(Runtime::kResolvePossiblyDirectEval, 2); - - // Touch up the stack with the right values for the function and the - // receiver. Use a scratch register to avoid destroying the result. - Result scratch = allocator_->Allocate(); - ASSERT(scratch.is_valid()); - __ movq(scratch.reg(), - FieldOperand(result.reg(), FixedArray::OffsetOfElementAt(0))); - frame_->SetElementAt(arg_count + 1, &scratch); - - // We can reuse the result register now. - frame_->Spill(result.reg()); - __ movq(result.reg(), - FieldOperand(result.reg(), FixedArray::OffsetOfElementAt(1))); - frame_->SetElementAt(arg_count, &result); - - // Call the function. - CodeForSourcePosition(node->position()); - InLoopFlag in_loop = loop_nesting() > 0 ? IN_LOOP : NOT_IN_LOOP; - CallFunctionStub call_function(arg_count, in_loop); - result = frame_->CallStub(&call_function, arg_count + 1); - - // Restore the context and overwrite the function on the stack with - // the result. - frame_->RestoreContextRegister(); - frame_->SetElementAt(0, &result); -} void CodeGenerator::VisitCallNew(CallNew* node) { --~--~---------~--~----~------------~-------~--~----~ v8-dev mailing list [email protected] http://groups.google.com/group/v8-dev -~----------~----~----~----~------~----~------~--~---
