From 928bfae4056ad4894f68e68345f39472d9acaccd Mon Sep 17 00:00:00 2001 From: "kmillikin@chromium.org" Date: Tue, 29 Sep 2009 13:28:30 +0000 Subject: [PATCH] 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 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@2984 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- src/arm/codegen-arm.cc | 110 +++++++++++++++++------------------ src/ast.cc | 1 - src/ast.h | 19 ------ src/cfg.cc | 5 -- src/ia32/codegen-ia32.cc | 118 +++++++++++++++++++------------------- src/parser.cc | 22 +------ src/prettyprinter.cc | 10 ---- src/rewriter.cc | 12 ---- src/usage-analyzer.cc | 6 -- src/variables.h | 8 ++- src/x64/codegen-x64.cc | 121 ++++++++++++++++++++------------------- 11 files changed, 178 insertions(+), 254 deletions(-) diff --git a/src/arm/codegen-arm.cc b/src/arm/codegen-arm.cc index 30ee3d660..f4a39ddb4 100644 --- a/src/arm/codegen-arm.cc +++ b/src/arm/codegen-arm.cc @@ -2907,11 +2907,11 @@ void CodeGenerator::VisitCall(Call* node) { VirtualFrame::SpilledScope spilled_scope; Comment cmnt(masm_, "[ Call"); + Expression* function = node->expression(); ZoneList* 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,7 +2924,56 @@ void CodeGenerator::VisitCall(Call* node) { // 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 // ---------------------------------- @@ -3049,63 +3098,6 @@ void CodeGenerator::VisitCall(Call* node) { } -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* 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) { #ifdef DEBUG int original_height = frame_->height(); diff --git a/src/ast.cc b/src/ast.cc index 2b6074200..692bec01d 100644 --- a/src/ast.cc +++ b/src/ast.cc @@ -40,7 +40,6 @@ VariableProxySentinel VariableProxySentinel::identifier_proxy_(false); ValidLeftHandSideSentinel ValidLeftHandSideSentinel::instance_; Property Property::this_property_(VariableProxySentinel::this_proxy(), NULL, 0); Call Call::sentinel_(NULL, NULL, 0); -CallEval CallEval::sentinel_(NULL, NULL, 0); // ---------------------------------------------------------------------------- diff --git a/src/ast.h b/src/ast.h index 99a14d248..905979b05 100644 --- a/src/ast.h +++ b/src/ast.h @@ -85,7 +85,6 @@ namespace internal { V(Throw) \ V(Property) \ V(Call) \ - V(CallEval) \ V(CallNew) \ V(CallRuntime) \ V(UnaryOperation) \ @@ -991,24 +990,6 @@ class CallNew: public Call { }; -// 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* 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 diff --git a/src/cfg.cc b/src/cfg.cc index d2dff522b..b87939258 100644 --- a/src/cfg.cc +++ b/src/cfg.cc @@ -398,11 +398,6 @@ void ExpressionCfgBuilder::VisitCall(Call* expr) { } -void ExpressionCfgBuilder::VisitCallEval(CallEval* expr) { - BAILOUT("CallEval"); -} - - void ExpressionCfgBuilder::VisitCallNew(CallNew* expr) { BAILOUT("CallNew"); } diff --git a/src/ia32/codegen-ia32.cc b/src/ia32/codegen-ia32.cc index ed7541f25..19709e51c 100644 --- a/src/ia32/codegen-ia32.cc +++ b/src/ia32/codegen-ia32.cc @@ -4431,10 +4431,10 @@ void CodeGenerator::VisitProperty(Property* node) { void CodeGenerator::VisitCall(Call* node) { Comment cmnt(masm_, "[ Call"); + Expression* function = node->expression(); ZoneList* 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,7 +4447,63 @@ void CodeGenerator::VisitCall(Call* node) { // 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 // ---------------------------------- @@ -4616,64 +4672,6 @@ void CodeGenerator::VisitCallNew(CallNew* node) { } -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* 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* args) { ASSERT(args->length() == 1); Load(args->at(0)); diff --git a/src/parser.cc b/src/parser.cc index 0abb9ed77..fb16a8be1 100644 --- a/src/parser.cc +++ b/src/parser.cc @@ -798,12 +798,6 @@ class ParserFactory BASE_EMBEDDED { return Call::sentinel(); } - virtual Expression* NewCallEval(Expression* expression, - ZoneList* arguments, - int pos) { - return CallEval::sentinel(); - } - virtual Statement* EmptyStatement() { return NULL; } @@ -854,12 +848,6 @@ class AstBuildingParserFactory : public ParserFactory { return new Call(expression, arguments, pos); } - virtual Expression* NewCallEval(Expression* expression, - ZoneList* arguments, - int pos) { - return new CallEval(expression, arguments, pos); - } - virtual Statement* EmptyStatement(); }; @@ -3074,8 +3062,6 @@ Expression* Parser::ParseLeftHandSideExpression(bool* ok) { // 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 @@ Expression* Parser::ParseLeftHandSideExpression(bool* ok) { 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; } diff --git a/src/prettyprinter.cc b/src/prettyprinter.cc index 7a8af40fd..bf66c4b5c 100644 --- a/src/prettyprinter.cc +++ b/src/prettyprinter.cc @@ -358,11 +358,6 @@ void PrettyPrinter::VisitCall(Call* node) { } -void PrettyPrinter::VisitCallEval(CallEval* node) { - VisitCall(node); -} - - void PrettyPrinter::VisitCallNew(CallNew* node) { Print("new ("); Visit(node->expression()); @@ -1040,11 +1035,6 @@ void AstPrinter::VisitCall(Call* node) { } -void AstPrinter::VisitCallEval(CallEval* node) { - VisitCall(node); -} - - void AstPrinter::VisitCallNew(CallNew* node) { IndentedScope indent("CALL NEW"); Visit(node->expression()); diff --git a/src/rewriter.cc b/src/rewriter.cc index d6ea68e69..11fc071f0 100644 --- a/src/rewriter.cc +++ b/src/rewriter.cc @@ -383,12 +383,6 @@ void AstOptimizer::VisitCall(Call* node) { } -void AstOptimizer::VisitCallEval(CallEval* node) { - Visit(node->expression()); - OptimizeArguments(node->arguments()); -} - - void AstOptimizer::VisitCallNew(CallNew* node) { Visit(node->expression()); OptimizeArguments(node->arguments()); @@ -759,12 +753,6 @@ void Processor::VisitCall(Call* node) { } -void Processor::VisitCallEval(CallEval* node) { - USE(node); - UNREACHABLE(); -} - - void Processor::VisitCallNew(CallNew* node) { USE(node); UNREACHABLE(); diff --git a/src/usage-analyzer.cc b/src/usage-analyzer.cc index 5514f405c..57cc14e6a 100644 --- a/src/usage-analyzer.cc +++ b/src/usage-analyzer.cc @@ -75,7 +75,6 @@ class UsageComputer: public AstVisitor { 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); @@ -329,11 +328,6 @@ void UsageComputer::VisitCall(Call* node) { } -void UsageComputer::VisitCallEval(CallEval* node) { - VisitCall(node); -} - - void UsageComputer::VisitCallNew(CallNew* node) { VisitCall(node); } diff --git a/src/variables.h b/src/variables.h index c2adb230c..ca78b5fc1 100644 --- a/src/variables.h +++ b/src/variables.h @@ -171,7 +171,7 @@ class Variable: public ZoneObject { UseCount* var_uses() { return &var_uses_; } UseCount* obj_uses() { return &obj_uses_; } - bool IsVariable(Handle n) { + bool IsVariable(Handle n) const { return !is_this() && name().is_identical_to(n); } @@ -185,6 +185,12 @@ class Variable: public ZoneObject { 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); return local_if_not_shadowed_; diff --git a/src/x64/codegen-x64.cc b/src/x64/codegen-x64.cc index 273affb14..bc64bcab4 100644 --- a/src/x64/codegen-x64.cc +++ b/src/x64/codegen-x64.cc @@ -2704,7 +2704,64 @@ void CodeGenerator::VisitCall(Call* node) { // 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 @@ void CodeGenerator::VisitCall(Call* node) { 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 @@ void CodeGenerator::VisitCall(Call* node) { // 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 @@ void CodeGenerator::VisitCall(Call* node) { // Call the function. CallWithArguments(args, node->position()); } + } else { // ---------------------------------- // JavaScript example: 'foo(1, 2, 3)' // foo is not global @@ -2839,65 +2899,6 @@ void CodeGenerator::VisitCall(Call* node) { } -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* 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) { Comment cmnt(masm_, "[ CallNew"); -- 2.34.1