Collect AstNode type information

Review URL: https://chromiumcodereview.appspot.com/9221011

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@10631 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
jkummerow@chromium.org 2012-02-08 09:56:33 +00:00
parent 9463c00d64
commit d795b7c620
14 changed files with 1364 additions and 983 deletions

View File

@ -126,18 +126,7 @@ Assignment::Assignment(Isolate* isolate,
assignment_id_(GetNextId(isolate)),
block_start_(false),
block_end_(false),
is_monomorphic_(false) {
ASSERT(Token::IsAssignmentOp(op));
if (is_compound()) {
binary_operation_ =
new(isolate->zone()) BinaryOperation(isolate,
binary_op(),
target,
value,
pos + 1);
compound_load_id_ = GetNextId(isolate);
}
}
is_monomorphic_(false) { }
Token::Value Assignment::binary_op() const {
@ -179,6 +168,11 @@ LanguageMode FunctionLiteral::language_mode() const {
}
bool FunctionLiteral::ShouldSelfOptimize() {
return !flags()->Contains(kDontSelfOptimize);
}
ObjectLiteral::Property::Property(Literal* key, Expression* value) {
emit_store_ = true;
key_ = key;
@ -197,9 +191,7 @@ ObjectLiteral::Property::Property(Literal* key, Expression* value) {
ObjectLiteral::Property::Property(bool is_getter, FunctionLiteral* value) {
Isolate* isolate = Isolate::Current();
emit_store_ = true;
key_ = new(isolate->zone()) Literal(isolate, value->name());
value_ = value;
kind_ = is_getter ? GETTER : SETTER;
}
@ -431,223 +423,6 @@ bool Declaration::IsInlineable() const {
}
bool TargetCollector::IsInlineable() const {
UNREACHABLE();
return false;
}
bool ForInStatement::IsInlineable() const {
return false;
}
bool WithStatement::IsInlineable() const {
return false;
}
bool SwitchStatement::IsInlineable() const {
return false;
}
bool TryStatement::IsInlineable() const {
return false;
}
bool TryCatchStatement::IsInlineable() const {
return false;
}
bool TryFinallyStatement::IsInlineable() const {
return false;
}
bool DebuggerStatement::IsInlineable() const {
return false;
}
bool Throw::IsInlineable() const {
return exception()->IsInlineable();
}
bool MaterializedLiteral::IsInlineable() const {
// TODO(1322): Allow materialized literals.
return false;
}
bool FunctionLiteral::IsInlineable() const {
// TODO(1322): Allow materialized literals.
return false;
}
bool ThisFunction::IsInlineable() const {
return true;
}
bool SharedFunctionInfoLiteral::IsInlineable() const {
return false;
}
bool ForStatement::IsInlineable() const {
return (init() == NULL || init()->IsInlineable())
&& (cond() == NULL || cond()->IsInlineable())
&& (next() == NULL || next()->IsInlineable())
&& body()->IsInlineable();
}
bool WhileStatement::IsInlineable() const {
return cond()->IsInlineable()
&& body()->IsInlineable();
}
bool DoWhileStatement::IsInlineable() const {
return cond()->IsInlineable()
&& body()->IsInlineable();
}
bool ContinueStatement::IsInlineable() const {
return true;
}
bool BreakStatement::IsInlineable() const {
return true;
}
bool EmptyStatement::IsInlineable() const {
return true;
}
bool Literal::IsInlineable() const {
return true;
}
bool Block::IsInlineable() const {
const int count = statements_.length();
for (int i = 0; i < count; ++i) {
if (!statements_[i]->IsInlineable()) return false;
}
return true;
}
bool ExpressionStatement::IsInlineable() const {
return expression()->IsInlineable();
}
bool IfStatement::IsInlineable() const {
return condition()->IsInlineable()
&& then_statement()->IsInlineable()
&& else_statement()->IsInlineable();
}
bool ReturnStatement::IsInlineable() const {
return expression()->IsInlineable();
}
bool Conditional::IsInlineable() const {
return condition()->IsInlineable() && then_expression()->IsInlineable() &&
else_expression()->IsInlineable();
}
bool VariableProxy::IsInlineable() const {
return var()->IsUnallocated()
|| var()->IsStackAllocated()
|| var()->IsContextSlot();
}
bool Assignment::IsInlineable() const {
return target()->IsInlineable() && value()->IsInlineable();
}
bool Property::IsInlineable() const {
return obj()->IsInlineable() && key()->IsInlineable();
}
bool Call::IsInlineable() const {
if (!expression()->IsInlineable()) return false;
const int count = arguments()->length();
for (int i = 0; i < count; ++i) {
if (!arguments()->at(i)->IsInlineable()) return false;
}
return true;
}
bool CallNew::IsInlineable() const {
if (!expression()->IsInlineable()) return false;
const int count = arguments()->length();
for (int i = 0; i < count; ++i) {
if (!arguments()->at(i)->IsInlineable()) return false;
}
return true;
}
bool CallRuntime::IsInlineable() const {
// Don't try to inline JS runtime calls because we don't (currently) even
// optimize them.
if (is_jsruntime()) return false;
// Don't inline the %_ArgumentsLength or %_Arguments because their
// implementation will not work. There is no stack frame to get them
// from.
if (function()->intrinsic_type == Runtime::INLINE &&
(name()->IsEqualTo(CStrVector("_ArgumentsLength")) ||
name()->IsEqualTo(CStrVector("_Arguments")))) {
return false;
}
const int count = arguments()->length();
for (int i = 0; i < count; ++i) {
if (!arguments()->at(i)->IsInlineable()) return false;
}
return true;
}
bool UnaryOperation::IsInlineable() const {
return expression()->IsInlineable();
}
bool BinaryOperation::IsInlineable() const {
return left()->IsInlineable() && right()->IsInlineable();
}
bool CompareOperation::IsInlineable() const {
return left()->IsInlineable() && right()->IsInlineable();
}
bool CountOperation::IsInlineable() const {
return expression()->IsInlineable();
}
// ----------------------------------------------------------------------------
// Recording of type feedback
@ -1214,4 +989,164 @@ CaseClause::CaseClause(Isolate* isolate,
entry_id_(AstNode::GetNextId(isolate)) {
}
#define INCREASE_NODE_COUNT(NodeType) \
void AstConstructionVisitor::Visit##NodeType(NodeType* node) { \
increase_node_count(); \
}
INCREASE_NODE_COUNT(Declaration)
INCREASE_NODE_COUNT(Block)
INCREASE_NODE_COUNT(ExpressionStatement)
INCREASE_NODE_COUNT(EmptyStatement)
INCREASE_NODE_COUNT(IfStatement)
INCREASE_NODE_COUNT(ContinueStatement)
INCREASE_NODE_COUNT(BreakStatement)
INCREASE_NODE_COUNT(ReturnStatement)
INCREASE_NODE_COUNT(Conditional)
INCREASE_NODE_COUNT(Literal)
INCREASE_NODE_COUNT(Assignment)
INCREASE_NODE_COUNT(Throw)
INCREASE_NODE_COUNT(Property)
INCREASE_NODE_COUNT(UnaryOperation)
INCREASE_NODE_COUNT(CountOperation)
INCREASE_NODE_COUNT(BinaryOperation)
INCREASE_NODE_COUNT(CompareOperation)
INCREASE_NODE_COUNT(ThisFunction)
#undef INCREASE_NODE_COUNT
void AstConstructionVisitor::VisitWithStatement(WithStatement* node) {
increase_node_count();
add_flag(kDontOptimize);
add_flag(kDontInline);
}
void AstConstructionVisitor::VisitSwitchStatement(SwitchStatement* node) {
increase_node_count();
add_flag(kDontInline);
}
void AstConstructionVisitor::VisitDoWhileStatement(DoWhileStatement* node) {
increase_node_count();
add_flag(kDontSelfOptimize);
}
void AstConstructionVisitor::VisitWhileStatement(WhileStatement* node) {
increase_node_count();
add_flag(kDontSelfOptimize);
}
void AstConstructionVisitor::VisitForStatement(ForStatement* node) {
increase_node_count();
add_flag(kDontSelfOptimize);
}
void AstConstructionVisitor::VisitForInStatement(ForInStatement* node) {
increase_node_count();
add_flag(kDontOptimize);
add_flag(kDontInline);
add_flag(kDontSelfOptimize);
}
void AstConstructionVisitor::VisitTryCatchStatement(TryCatchStatement* node) {
increase_node_count();
add_flag(kDontOptimize);
add_flag(kDontInline);
}
void AstConstructionVisitor::VisitTryFinallyStatement(
TryFinallyStatement* node) {
increase_node_count();
add_flag(kDontOptimize);
add_flag(kDontInline);
}
void AstConstructionVisitor::VisitDebuggerStatement(DebuggerStatement* node) {
increase_node_count();
add_flag(kDontOptimize);
add_flag(kDontInline);
}
void AstConstructionVisitor::VisitFunctionLiteral(FunctionLiteral* node) {
increase_node_count();
add_flag(kDontInline);
}
void AstConstructionVisitor::VisitSharedFunctionInfoLiteral(
SharedFunctionInfoLiteral* node) {
increase_node_count();
add_flag(kDontOptimize);
add_flag(kDontInline);
}
void AstConstructionVisitor::VisitVariableProxy(VariableProxy* node) {
increase_node_count();
// In theory, we'd have to add:
// if(node->var()->IsLookupSlot()) { add_flag(kDontInline); }
// However, node->var() is usually not bound yet at VariableProxy creation
// time, and LOOKUP variables only result from constructs that cannot
// be inlined anyway.
}
void AstConstructionVisitor::VisitRegExpLiteral(RegExpLiteral* node) {
increase_node_count();
add_flag(kDontInline); // TODO(1322): Allow materialized literals.
}
void AstConstructionVisitor::VisitObjectLiteral(ObjectLiteral* node) {
increase_node_count();
add_flag(kDontInline); // TODO(1322): Allow materialized literals.
}
void AstConstructionVisitor::VisitArrayLiteral(ArrayLiteral* node) {
increase_node_count();
add_flag(kDontInline); // TODO(1322): Allow materialized literals.
}
void AstConstructionVisitor::VisitCall(Call* node) {
increase_node_count();
add_flag(kDontSelfOptimize);
}
void AstConstructionVisitor::VisitCallNew(CallNew* node) {
increase_node_count();
add_flag(kDontSelfOptimize);
}
void AstConstructionVisitor::VisitCallRuntime(CallRuntime* node) {
increase_node_count();
add_flag(kDontSelfOptimize);
if (node->is_jsruntime()) {
// Don't try to inline JS runtime calls because we don't (currently) even
// optimize them.
add_flag(kDontInline);
} else if (node->function()->intrinsic_type == Runtime::INLINE &&
(node->name()->IsEqualTo(CStrVector("_ArgumentsLength")) ||
node->name()->IsEqualTo(CStrVector("_Arguments")))) {
// Don't inline the %_ArgumentsLength or %_Arguments because their
// implementation will not work. There is no stack frame to get them
// from.
add_flag(kDontInline);
}
}
} } // namespace v8::internal

1175
src/ast.h

File diff suppressed because it is too large Load Diff

View File

@ -1,4 +1,4 @@
// Copyright 2011 the V8 project authors. All rights reserved.
// Copyright 2012 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:
@ -652,6 +652,8 @@ bool Compiler::CompileLazy(CompilationInfo* info) {
// Check the function has compiled code.
ASSERT(shared->is_compiled());
shared->set_code_age(0);
shared->set_dont_crankshaft(lit->flags()->Contains(kDontOptimize));
shared->set_dont_inline(lit->flags()->Contains(kDontInline));
if (info->AllowOptimize() && !shared->optimization_disabled()) {
// If we're asked to always optimize, we compile the optimized
@ -750,6 +752,9 @@ void Compiler::SetFunctionInfo(Handle<SharedFunctionInfo> function_info,
function_info->set_language_mode(lit->language_mode());
function_info->set_uses_arguments(lit->scope()->arguments() != NULL);
function_info->set_has_duplicate_parameters(lit->has_duplicate_parameters());
function_info->set_ast_node_count(lit->ast_node_count());
function_info->set_dont_crankshaft(lit->flags()->Contains(kDontOptimize));
function_info->set_dont_inline(lit->flags()->Contains(kDontInline));
}

View File

@ -2865,7 +2865,8 @@ MaybeObject* Heap::AllocateSharedFunctionInfo(Object* name) {
share->set_inferred_name(empty_string(), SKIP_WRITE_BARRIER);
share->set_initial_map(undefined_value(), SKIP_WRITE_BARRIER);
share->set_this_property_assignments(undefined_value(), SKIP_WRITE_BARRIER);
share->set_deopt_counter(Smi::FromInt(FLAG_deopt_every_n_times));
share->set_deopt_counter(FLAG_deopt_every_n_times);
share->set_ast_node_count(0);
// Set integer fields (smi or int, depending on the architecture).
share->set_length(0);

View File

@ -4796,8 +4796,8 @@ bool HGraphBuilder::TryInline(Call* expr, bool drop_extra) {
// Do a quick check on source code length to avoid parsing large
// inlining candidates.
if ((FLAG_limit_inlining && target->shared()->SourceSize() > kMaxSourceSize)
|| target->shared()->SourceSize() > kUnlimitedMaxSourceSize) {
if ((FLAG_limit_inlining && target_shared->SourceSize() > kMaxSourceSize)
|| target_shared->SourceSize() > kUnlimitedMaxSourceSize) {
TraceInline(target, caller, "target text too big");
return false;
}
@ -4807,6 +4807,17 @@ bool HGraphBuilder::TryInline(Call* expr, bool drop_extra) {
TraceInline(target, caller, "target not inlineable");
return false;
}
if (target_shared->dont_inline() || target_shared->dont_crankshaft()) {
TraceInline(target, caller, "target contains unsupported syntax [early]");
return false;
}
int nodes_added = target_shared->ast_node_count();
if ((FLAG_limit_inlining && nodes_added > kMaxInlinedSize) ||
nodes_added > kUnlimitedMaxInlinedSize) {
TraceInline(target, caller, "target AST is too large [early]");
return false;
}
#if !defined(V8_TARGET_ARCH_IA32)
// Target must be able to use caller's context.
@ -4851,8 +4862,6 @@ bool HGraphBuilder::TryInline(Call* expr, bool drop_extra) {
return false;
}
int count_before = AstNode::Count();
// Parse and allocate variables.
CompilationInfo target_info(target);
if (!ParserApi::Parse(&target_info, kNoParsingFlags) ||
@ -4872,11 +4881,17 @@ bool HGraphBuilder::TryInline(Call* expr, bool drop_extra) {
}
FunctionLiteral* function = target_info.function();
// Count the number of AST nodes added by inlining this call.
int nodes_added = AstNode::Count() - count_before;
// The following conditions must be checked again after re-parsing, because
// earlier the information might not have been complete due to lazy parsing.
nodes_added = function->ast_node_count();
if ((FLAG_limit_inlining && nodes_added > kMaxInlinedSize) ||
nodes_added > kUnlimitedMaxInlinedSize) {
TraceInline(target, caller, "target AST is too large");
TraceInline(target, caller, "target AST is too large [late]");
return false;
}
AstProperties::Flags* flags(function->flags());
if (flags->Contains(kDontInline) || flags->Contains(kDontOptimize)) {
TraceInline(target, caller, "target contains unsupported syntax [late]");
return false;
}
@ -4895,13 +4910,6 @@ bool HGraphBuilder::TryInline(Call* expr, bool drop_extra) {
return false;
}
}
// All statements in the body must be inlineable.
for (int i = 0, count = function->body()->length(); i < count; ++i) {
if (!function->body()->at(i)->IsInlineable()) {
TraceInline(target, caller, "target contains unsupported syntax");
return false;
}
}
// Generate the deoptimization data for the unoptimized version of
// the target function if we don't already have it.

View File

@ -362,7 +362,7 @@ typedef List<HeapObject*, PreallocatedStorage> DebugObjectCache;
/* Serializer state. */ \
V(ExternalReferenceTable*, external_reference_table, NULL) \
/* AstNode state. */ \
V(unsigned, ast_node_id, 0) \
V(int, ast_node_id, 0) \
V(unsigned, ast_node_count, 0) \
/* SafeStackFrameIterator activations count. */ \
V(int, safe_stack_iterator_counter, 0) \

View File

@ -3576,6 +3576,8 @@ SMI_ACCESSORS(SharedFunctionInfo, compiler_hints,
SMI_ACCESSORS(SharedFunctionInfo, this_property_assignments_count,
kThisPropertyAssignmentsCountOffset)
SMI_ACCESSORS(SharedFunctionInfo, opt_count, kOptCountOffset)
SMI_ACCESSORS(SharedFunctionInfo, ast_node_count, kAstNodeCountOffset)
SMI_ACCESSORS(SharedFunctionInfo, deopt_counter, kDeoptCounterOffset)
#else
#define PSEUDO_SMI_ACCESSORS_LO(holder, name, offset) \
@ -3626,6 +3628,9 @@ PSEUDO_SMI_ACCESSORS_LO(SharedFunctionInfo,
this_property_assignments_count,
kThisPropertyAssignmentsCountOffset)
PSEUDO_SMI_ACCESSORS_HI(SharedFunctionInfo, opt_count, kOptCountOffset)
PSEUDO_SMI_ACCESSORS_LO(SharedFunctionInfo, ast_node_count, kAstNodeCountOffset)
PSEUDO_SMI_ACCESSORS_HI(SharedFunctionInfo, deopt_counter, kDeoptCounterOffset)
#endif
@ -3708,6 +3713,9 @@ BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints,
kNameShouldPrintAsAnonymous)
BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, bound, kBoundFunction)
BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, is_anonymous, kIsAnonymous)
BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, dont_crankshaft,
kDontCrankshaft)
BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, dont_inline, kDontInline)
ACCESSORS(CodeCache, default_cache, FixedArray, kDefaultCacheOffset)
ACCESSORS(CodeCache, normal_type_cache, Object, kNormalTypeCacheOffset)
@ -3777,16 +3785,6 @@ void SharedFunctionInfo::set_scope_info(ScopeInfo* value,
}
Smi* SharedFunctionInfo::deopt_counter() {
return reinterpret_cast<Smi*>(READ_FIELD(this, kDeoptCounterOffset));
}
void SharedFunctionInfo::set_deopt_counter(Smi* value) {
WRITE_FIELD(this, kDeoptCounterOffset, value);
}
bool SharedFunctionInfo::is_compiled() {
return code() !=
Isolate::Current()->builtins()->builtin(Builtins::kLazyCompile);

View File

@ -5203,8 +5203,11 @@ class SharedFunctionInfo: public HeapObject {
// A counter used to determine when to stress the deoptimizer with a
// deopt.
inline Smi* deopt_counter();
inline void set_deopt_counter(Smi* counter);
inline int deopt_counter();
inline void set_deopt_counter(int counter);
inline int ast_node_count();
inline void set_ast_node_count(int count);
// Add information on assignments of the form this.x = ...;
void SetThisPropertyAssignmentsInfo(
@ -5278,6 +5281,12 @@ class SharedFunctionInfo: public HeapObject {
// through the API, which does not change this flag).
DECL_BOOLEAN_ACCESSORS(is_anonymous)
// Indicates that the function cannot be crankshafted.
DECL_BOOLEAN_ACCESSORS(dont_crankshaft)
// Indicates that the function cannot be inlined.
DECL_BOOLEAN_ACCESSORS(dont_inline)
// Indicates whether or not the code in the shared function support
// deoptimization.
inline bool has_deoptimization_support();
@ -5372,12 +5381,10 @@ class SharedFunctionInfo: public HeapObject {
kInferredNameOffset + kPointerSize;
static const int kThisPropertyAssignmentsOffset =
kInitialMapOffset + kPointerSize;
static const int kDeoptCounterOffset =
kThisPropertyAssignmentsOffset + kPointerSize;
#if V8_HOST_ARCH_32_BIT
// Smi fields.
static const int kLengthOffset =
kDeoptCounterOffset + kPointerSize;
kThisPropertyAssignmentsOffset + kPointerSize;
static const int kFormalParameterCountOffset = kLengthOffset + kPointerSize;
static const int kExpectedNofPropertiesOffset =
kFormalParameterCountOffset + kPointerSize;
@ -5395,8 +5402,11 @@ class SharedFunctionInfo: public HeapObject {
kCompilerHintsOffset + kPointerSize;
static const int kOptCountOffset =
kThisPropertyAssignmentsCountOffset + kPointerSize;
static const int kAstNodeCountOffset = kOptCountOffset + kPointerSize;
static const int kDeoptCounterOffset =
kAstNodeCountOffset + kPointerSize;
// Total size.
static const int kSize = kOptCountOffset + kPointerSize;
static const int kSize = kDeoptCounterOffset + kPointerSize;
#else
// The only reason to use smi fields instead of int fields
// is to allow iteration without maps decoding during
@ -5408,7 +5418,7 @@ class SharedFunctionInfo: public HeapObject {
// word is not set and thus this word cannot be treated as pointer
// to HeapObject during old space traversal.
static const int kLengthOffset =
kDeoptCounterOffset + kPointerSize;
kThisPropertyAssignmentsOffset + kPointerSize;
static const int kFormalParameterCountOffset =
kLengthOffset + kIntSize;
@ -5432,8 +5442,11 @@ class SharedFunctionInfo: public HeapObject {
static const int kOptCountOffset =
kThisPropertyAssignmentsCountOffset + kIntSize;
static const int kAstNodeCountOffset = kOptCountOffset + kIntSize;
static const int kDeoptCounterOffset = kAstNodeCountOffset + kIntSize;
// Total size.
static const int kSize = kOptCountOffset + kIntSize;
static const int kSize = kDeoptCounterOffset + kIntSize;
#endif
@ -5480,6 +5493,8 @@ class SharedFunctionInfo: public HeapObject {
kBoundFunction,
kIsAnonymous,
kNameShouldPrintAsAnonymous,
kDontCrankshaft,
kDontInline,
kCompilerHintsCount // Pseudo entry
};

View File

@ -481,62 +481,6 @@ class Parser::BlockState BASE_EMBEDDED {
};
class Parser::FunctionState BASE_EMBEDDED {
public:
FunctionState(Parser* parser, Scope* scope, Isolate* isolate);
~FunctionState();
int NextMaterializedLiteralIndex() {
return next_materialized_literal_index_++;
}
int materialized_literal_count() {
return next_materialized_literal_index_ - JSFunction::kLiteralsPrefixSize;
}
int NextHandlerIndex() { return next_handler_index_++; }
int handler_count() { return next_handler_index_; }
void SetThisPropertyAssignmentInfo(
bool only_simple_this_property_assignments,
Handle<FixedArray> this_property_assignments) {
only_simple_this_property_assignments_ =
only_simple_this_property_assignments;
this_property_assignments_ = this_property_assignments;
}
bool only_simple_this_property_assignments() {
return only_simple_this_property_assignments_;
}
Handle<FixedArray> this_property_assignments() {
return this_property_assignments_;
}
void AddProperty() { expected_property_count_++; }
int expected_property_count() { return expected_property_count_; }
private:
// Used to assign an index to each literal that needs materialization in
// the function. Includes regexp literals, and boilerplate for object and
// array literals.
int next_materialized_literal_index_;
// Used to assign a per-function index to try and catch handlers.
int next_handler_index_;
// Properties count estimation.
int expected_property_count_;
// Keeps track of assignments to properties of this. Used for
// optimizing constructors.
bool only_simple_this_property_assignments_;
Handle<FixedArray> this_property_assignments_;
Parser* parser_;
FunctionState* outer_function_state_;
Scope* outer_scope_;
unsigned saved_ast_node_id_;
};
Parser::FunctionState::FunctionState(Parser* parser,
Scope* scope,
Isolate* isolate)
@ -548,7 +492,8 @@ Parser::FunctionState::FunctionState(Parser* parser,
parser_(parser),
outer_function_state_(parser->current_function_state_),
outer_scope_(parser->top_scope_),
saved_ast_node_id_(isolate->ast_node_id()) {
saved_ast_node_id_(isolate->ast_node_id()),
factory_(isolate) {
parser->top_scope_ = scope;
parser->current_function_state_ = this;
isolate->set_ast_node_id(AstNode::kDeclarationsId + 1);
@ -674,8 +619,7 @@ FunctionLiteral* Parser::DoParseProgram(CompilationInfo* info,
}
if (ok) {
result = new(zone()) FunctionLiteral(
isolate(),
result = factory()->NewFunctionLiteral(
no_name,
top_scope_,
body,
@ -685,8 +629,10 @@ FunctionLiteral* Parser::DoParseProgram(CompilationInfo* info,
function_state.only_simple_this_property_assignments(),
function_state.this_property_assignments(),
0,
false, // Does not have duplicate parameters.
FunctionLiteral::ANONYMOUS_EXPRESSION,
false); // Does not have duplicate parameters.
false); // Top-level literal doesn't count for the AST's properties.
result->set_ast_properties(factory()->visitor()->ast_properties());
} else if (stack_overflow_) {
isolate()->StackOverflow();
}
@ -1274,7 +1220,7 @@ Statement* Parser::ParseStatement(ZoneStringList* labels, bool* ok) {
case Token::SEMICOLON:
Next();
return EmptyStatement();
return factory()->NewEmptyStatement();
case Token::IF:
stmt = ParseIfStatement(labels, ok);
@ -1322,7 +1268,7 @@ Statement* Parser::ParseStatement(ZoneStringList* labels, bool* ok) {
// one must take great care not to treat it as a
// fall-through. It is much easier just to wrap the entire
// try-statement in a statement block and put the labels there
Block* result = new(zone()) Block(isolate(), labels, 1, false);
Block* result = factory()->NewBlock(labels, 1, false);
Target target(&this->target_stack_, result);
TryStatement* statement = ParseTryStatement(CHECK_OK);
if (statement) {
@ -1454,9 +1400,9 @@ VariableProxy* Parser::Declare(Handle<String> name,
// a performance issue since it may lead to repeated
// Runtime::DeclareContextSlot() calls.
VariableProxy* proxy = declaration_scope->NewUnresolved(
name, scanner().location().beg_pos);
factory(), name, scanner().location().beg_pos);
declaration_scope->AddDeclaration(
new(zone()) Declaration(proxy, mode, fun, top_scope_));
factory()->NewDeclaration(proxy, mode, fun, top_scope_));
if ((mode == CONST || mode == CONST_HARMONY) &&
declaration_scope->is_global_scope()) {
@ -1564,10 +1510,11 @@ Statement* Parser::ParseNativeDeclaration(bool* ok) {
// introduced dynamically when we meet their declarations, whereas
// other functions are set up when entering the surrounding scope.
SharedFunctionInfoLiteral* lit =
new(zone()) SharedFunctionInfoLiteral(isolate(), shared);
factory()->NewSharedFunctionInfoLiteral(shared);
VariableProxy* var = Declare(name, VAR, NULL, true, CHECK_OK);
return new(zone()) ExpressionStatement(new(zone()) Assignment(
isolate(), Token::INIT_VAR, var, lit, RelocInfo::kNoPosition));
return factory()->NewExpressionStatement(
factory()->NewAssignment(
Token::INIT_VAR, var, lit, RelocInfo::kNoPosition));
}
@ -1589,7 +1536,7 @@ Statement* Parser::ParseFunctionDeclaration(bool* ok) {
// initial value upon entering the corresponding scope.
VariableMode mode = is_extended_mode() ? LET : VAR;
Declare(name, mode, fun, true, CHECK_OK);
return EmptyStatement();
return factory()->NewEmptyStatement();
}
@ -1603,7 +1550,7 @@ Block* Parser::ParseBlock(ZoneStringList* labels, bool* ok) {
// (ECMA-262, 3rd, 12.2)
//
// Construct block expecting 16 statements.
Block* result = new(zone()) Block(isolate(), labels, 16, false);
Block* result = factory()->NewBlock(labels, 16, false);
Target target(&this->target_stack_, result);
Expect(Token::LBRACE, CHECK_OK);
InitializationBlockFinder block_finder(top_scope_, target_stack_);
@ -1626,7 +1573,7 @@ Block* Parser::ParseScopedBlock(ZoneStringList* labels, bool* ok) {
// '{' SourceElement* '}'
// Construct block expecting 16 statements.
Block* body = new(zone()) Block(isolate(), labels, 16, false);
Block* body = factory()->NewBlock(labels, 16, false);
Scope* block_scope = NewScope(top_scope_, BLOCK_SCOPE);
// Parse the statements and collect escaping labels.
@ -1786,7 +1733,7 @@ Block* Parser::ParseVariableDeclarations(
// is inside an initializer block, it is ignored.
//
// Create new block with one expected declaration.
Block* block = new(zone()) Block(isolate(), NULL, 1, true);
Block* block = factory()->NewBlock(NULL, 1, true);
int nvars = 0; // the number of variables declared
Handle<String> name;
do {
@ -1907,7 +1854,7 @@ Block* Parser::ParseVariableDeclarations(
// Compute the arguments for the runtime call.
ZoneList<Expression*>* arguments = new(zone()) ZoneList<Expression*>(3);
// We have at least 1 parameter.
arguments->Add(NewLiteral(name));
arguments->Add(factory()->NewLiteral(name));
CallRuntime* initialize;
if (is_const) {
@ -1918,17 +1865,15 @@ Block* Parser::ParseVariableDeclarations(
// and add it to the initialization statement block.
// Note that the function does different things depending on
// the number of arguments (1 or 2).
initialize =
new(zone()) CallRuntime(
isolate(),
isolate()->factory()->InitializeConstGlobal_symbol(),
Runtime::FunctionForId(Runtime::kInitializeConstGlobal),
arguments);
initialize = factory()->NewCallRuntime(
isolate()->factory()->InitializeConstGlobal_symbol(),
Runtime::FunctionForId(Runtime::kInitializeConstGlobal),
arguments);
} else {
// Add strict mode.
// We may want to pass singleton to avoid Literal allocations.
LanguageMode language_mode = initialization_scope->language_mode();
arguments->Add(NewNumberLiteral(language_mode));
arguments->Add(factory()->NewNumberLiteral(language_mode));
// Be careful not to assign a value to the global variable if
// we're in a with. The initialization value should not
@ -1943,15 +1888,13 @@ Block* Parser::ParseVariableDeclarations(
// and add it to the initialization statement block.
// Note that the function does different things depending on
// the number of arguments (2 or 3).
initialize =
new(zone()) CallRuntime(
isolate(),
isolate()->factory()->InitializeVarGlobal_symbol(),
Runtime::FunctionForId(Runtime::kInitializeVarGlobal),
arguments);
initialize = factory()->NewCallRuntime(
isolate()->factory()->InitializeVarGlobal_symbol(),
Runtime::FunctionForId(Runtime::kInitializeVarGlobal),
arguments);
}
block->AddStatement(new(zone()) ExpressionStatement(initialize));
block->AddStatement(factory()->NewExpressionStatement(initialize));
} else if (needs_init) {
// Constant initializations always assign to the declared constant which
// is always at the function scope level. This is only relevant for
@ -1964,8 +1907,8 @@ Block* Parser::ParseVariableDeclarations(
ASSERT(proxy->var() != NULL);
ASSERT(value != NULL);
Assignment* assignment =
new(zone()) Assignment(isolate(), init_op, proxy, value, position);
block->AddStatement(new(zone()) ExpressionStatement(assignment));
factory()->NewAssignment(init_op, proxy, value, position);
block->AddStatement(factory()->NewExpressionStatement(assignment));
value = NULL;
}
@ -1976,10 +1919,11 @@ Block* Parser::ParseVariableDeclarations(
// 'var' initializations are simply assignments (with all the consequences
// if they are inside a 'with' statement - they may change a 'with' object
// property).
VariableProxy* proxy = initialization_scope->NewUnresolved(name);
VariableProxy* proxy =
initialization_scope->NewUnresolved(factory(), name);
Assignment* assignment =
new(zone()) Assignment(isolate(), init_op, proxy, value, position);
block->AddStatement(new(zone()) ExpressionStatement(assignment));
factory()->NewAssignment(init_op, proxy, value, position);
block->AddStatement(factory()->NewExpressionStatement(assignment));
}
if (fni_ != NULL) fni_->Leave();
@ -2059,7 +2003,7 @@ Statement* Parser::ParseExpressionOrLabelledStatement(ZoneStringList* labels,
// Parsed expression statement.
ExpectSemicolon(CHECK_OK);
return new(zone()) ExpressionStatement(expr);
return factory()->NewExpressionStatement(expr);
}
@ -2077,10 +2021,9 @@ IfStatement* Parser::ParseIfStatement(ZoneStringList* labels, bool* ok) {
Next();
else_statement = ParseStatement(labels, CHECK_OK);
} else {
else_statement = EmptyStatement();
else_statement = factory()->NewEmptyStatement();
}
return new(zone()) IfStatement(
isolate(), condition, then_statement, else_statement);
return factory()->NewIfStatement(condition, then_statement, else_statement);
}
@ -2110,7 +2053,7 @@ Statement* Parser::ParseContinueStatement(bool* ok) {
return NULL;
}
ExpectSemicolon(CHECK_OK);
return new(zone()) ContinueStatement(target);
return factory()->NewContinueStatement(target);
}
@ -2129,7 +2072,7 @@ Statement* Parser::ParseBreakStatement(ZoneStringList* labels, bool* ok) {
// empty statements, e.g. 'l1: l2: l3: break l2;'
if (!label.is_null() && ContainsLabel(labels, label)) {
ExpectSemicolon(CHECK_OK);
return EmptyStatement();
return factory()->NewEmptyStatement();
}
BreakableStatement* target = NULL;
target = LookupBreakTarget(label, CHECK_OK);
@ -2146,7 +2089,7 @@ Statement* Parser::ParseBreakStatement(ZoneStringList* labels, bool* ok) {
return NULL;
}
ExpectSemicolon(CHECK_OK);
return new(zone()) BreakStatement(target);
return factory()->NewBreakStatement(target);
}
@ -2166,11 +2109,11 @@ Statement* Parser::ParseReturnStatement(bool* ok) {
tok == Token::RBRACE ||
tok == Token::EOS) {
ExpectSemicolon(CHECK_OK);
result = new(zone()) ReturnStatement(GetLiteralUndefined());
result = factory()->NewReturnStatement(GetLiteralUndefined());
} else {
Expression* expr = ParseExpression(true, CHECK_OK);
ExpectSemicolon(CHECK_OK);
result = new(zone()) ReturnStatement(expr);
result = factory()->NewReturnStatement(expr);
}
// An ECMAScript program is considered syntactically incorrect if it
@ -2183,7 +2126,7 @@ Statement* Parser::ParseReturnStatement(bool* ok) {
declaration_scope->is_eval_scope()) {
Handle<String> type = isolate()->factory()->illegal_return_symbol();
Expression* throw_error = NewThrowSyntaxError(type, Handle<Object>::null());
return new(zone()) ExpressionStatement(throw_error);
return factory()->NewExpressionStatement(throw_error);
}
return result;
}
@ -2213,7 +2156,7 @@ Statement* Parser::ParseWithStatement(ZoneStringList* labels, bool* ok) {
stmt = ParseStatement(labels, CHECK_OK);
with_scope->set_end_position(scanner().location().end_pos);
}
return new(zone()) WithStatement(expr, stmt);
return factory()->NewWithStatement(expr, stmt);
}
@ -2255,7 +2198,7 @@ SwitchStatement* Parser::ParseSwitchStatement(ZoneStringList* labels,
// SwitchStatement ::
// 'switch' '(' Expression ')' '{' CaseClause* '}'
SwitchStatement* statement = new(zone()) SwitchStatement(isolate(), labels);
SwitchStatement* statement = factory()->NewSwitchStatement(labels);
Target target(&this->target_stack_, statement);
Expect(Token::SWITCH, CHECK_OK);
@ -2291,8 +2234,7 @@ Statement* Parser::ParseThrowStatement(bool* ok) {
Expression* exception = ParseExpression(true, CHECK_OK);
ExpectSemicolon(CHECK_OK);
return new(zone()) ExpressionStatement(
new(zone()) Throw(isolate(), exception, pos));
return factory()->NewExpressionStatement(factory()->NewThrow(exception, pos));
}
@ -2379,13 +2321,10 @@ TryStatement* Parser::ParseTryStatement(bool* ok) {
// If we have both, create an inner try/catch.
ASSERT(catch_scope != NULL && catch_variable != NULL);
int index = current_function_state_->NextHandlerIndex();
TryCatchStatement* statement = new(zone()) TryCatchStatement(index,
try_block,
catch_scope,
catch_variable,
catch_block);
TryCatchStatement* statement = factory()->NewTryCatchStatement(
index, try_block, catch_scope, catch_variable, catch_block);
statement->set_escaping_targets(try_collector.targets());
try_block = new(zone()) Block(isolate(), NULL, 1, false);
try_block = factory()->NewBlock(NULL, 1, false);
try_block->AddStatement(statement);
catch_block = NULL; // Clear to indicate it's been handled.
}
@ -2395,17 +2334,12 @@ TryStatement* Parser::ParseTryStatement(bool* ok) {
ASSERT(finally_block == NULL);
ASSERT(catch_scope != NULL && catch_variable != NULL);
int index = current_function_state_->NextHandlerIndex();
result = new(zone()) TryCatchStatement(index,
try_block,
catch_scope,
catch_variable,
catch_block);
result = factory()->NewTryCatchStatement(
index, try_block, catch_scope, catch_variable, catch_block);
} else {
ASSERT(finally_block != NULL);
int index = current_function_state_->NextHandlerIndex();
result = new(zone()) TryFinallyStatement(index,
try_block,
finally_block);
result = factory()->NewTryFinallyStatement(index, try_block, finally_block);
// Combine the jump targets of the try block and the possible catch block.
try_collector.targets()->AddAll(*catch_collector.targets());
}
@ -2420,7 +2354,7 @@ DoWhileStatement* Parser::ParseDoWhileStatement(ZoneStringList* labels,
// DoStatement ::
// 'do' Statement 'while' '(' Expression ')' ';'
DoWhileStatement* loop = new(zone()) DoWhileStatement(isolate(), labels);
DoWhileStatement* loop = factory()->NewDoWhileStatement(labels);
Target target(&this->target_stack_, loop);
Expect(Token::DO, CHECK_OK);
@ -2451,7 +2385,7 @@ WhileStatement* Parser::ParseWhileStatement(ZoneStringList* labels, bool* ok) {
// WhileStatement ::
// 'while' '(' Expression ')' Statement
WhileStatement* loop = new(zone()) WhileStatement(isolate(), labels);
WhileStatement* loop = factory()->NewWhileStatement(labels);
Target target(&this->target_stack_, loop);
Expect(Token::WHILE, CHECK_OK);
@ -2486,8 +2420,8 @@ Statement* Parser::ParseForStatement(ZoneStringList* labels, bool* ok) {
ParseVariableDeclarations(kForStatement, NULL, &name, CHECK_OK);
if (peek() == Token::IN && !name.is_null()) {
VariableProxy* each = top_scope_->NewUnresolved(name);
ForInStatement* loop = new(zone()) ForInStatement(isolate(), labels);
VariableProxy* each = top_scope_->NewUnresolved(factory(), name);
ForInStatement* loop = factory()->NewForInStatement(labels);
Target target(&this->target_stack_, loop);
Expect(Token::IN, CHECK_OK);
@ -2496,7 +2430,7 @@ Statement* Parser::ParseForStatement(ZoneStringList* labels, bool* ok) {
Statement* body = ParseStatement(NULL, CHECK_OK);
loop->Initialize(each, enumerable, body);
Block* result = new(zone()) Block(isolate(), NULL, 2, false);
Block* result = factory()->NewBlock(NULL, 2, false);
result->AddStatement(variable_statement);
result->AddStatement(loop);
top_scope_ = saved_scope;
@ -2534,9 +2468,9 @@ Statement* Parser::ParseForStatement(ZoneStringList* labels, bool* ok) {
// TODO(keuchel): Move the temporary variable to the block scope, after
// implementing stack allocated block scoped variables.
Variable* temp = top_scope_->DeclarationScope()->NewTemporary(name);
VariableProxy* temp_proxy = new(zone()) VariableProxy(isolate(), temp);
VariableProxy* each = top_scope_->NewUnresolved(name);
ForInStatement* loop = new(zone()) ForInStatement(isolate(), labels);
VariableProxy* temp_proxy = factory()->NewVariableProxy(temp);
VariableProxy* each = top_scope_->NewUnresolved(factory(), name);
ForInStatement* loop = factory()->NewForInStatement(labels);
Target target(&this->target_stack_, loop);
Expect(Token::IN, CHECK_OK);
@ -2544,14 +2478,11 @@ Statement* Parser::ParseForStatement(ZoneStringList* labels, bool* ok) {
Expect(Token::RPAREN, CHECK_OK);
Statement* body = ParseStatement(NULL, CHECK_OK);
Block* body_block = new(zone()) Block(isolate(), NULL, 3, false);
Assignment* assignment = new(zone()) Assignment(isolate(),
Token::ASSIGN,
each,
temp_proxy,
RelocInfo::kNoPosition);
Block* body_block = factory()->NewBlock(NULL, 3, false);
Assignment* assignment = factory()->NewAssignment(
Token::ASSIGN, each, temp_proxy, RelocInfo::kNoPosition);
Statement* assignment_statement =
new(zone()) ExpressionStatement(assignment);
factory()->NewExpressionStatement(assignment);
body_block->AddStatement(variable_statement);
body_block->AddStatement(assignment_statement);
body_block->AddStatement(body);
@ -2578,7 +2509,7 @@ Statement* Parser::ParseForStatement(ZoneStringList* labels, bool* ok) {
isolate()->factory()->invalid_lhs_in_for_in_symbol();
expression = NewThrowReferenceError(type);
}
ForInStatement* loop = new(zone()) ForInStatement(isolate(), labels);
ForInStatement* loop = factory()->NewForInStatement(labels);
Target target(&this->target_stack_, loop);
Expect(Token::IN, CHECK_OK);
@ -2595,13 +2526,13 @@ Statement* Parser::ParseForStatement(ZoneStringList* labels, bool* ok) {
return loop;
} else {
init = new(zone()) ExpressionStatement(expression);
init = factory()->NewExpressionStatement(expression);
}
}
}
// Standard 'for' loop
ForStatement* loop = new(zone()) ForStatement(isolate(), labels);
ForStatement* loop = factory()->NewForStatement(labels);
Target target(&this->target_stack_, loop);
// Parsed initializer at this point.
@ -2616,7 +2547,7 @@ Statement* Parser::ParseForStatement(ZoneStringList* labels, bool* ok) {
Statement* next = NULL;
if (peek() != Token::RPAREN) {
Expression* exp = ParseExpression(true, CHECK_OK);
next = new(zone()) ExpressionStatement(exp);
next = factory()->NewExpressionStatement(exp);
}
Expect(Token::RPAREN, CHECK_OK);
@ -2636,7 +2567,7 @@ Statement* Parser::ParseForStatement(ZoneStringList* labels, bool* ok) {
// for (; c; n) b
// }
ASSERT(init != NULL);
Block* result = new(zone()) Block(isolate(), NULL, 2, false);
Block* result = factory()->NewBlock(NULL, 2, false);
result->AddStatement(init);
result->AddStatement(loop);
result->set_block_scope(for_scope);
@ -2660,8 +2591,8 @@ Expression* Parser::ParseExpression(bool accept_IN, bool* ok) {
Expect(Token::COMMA, CHECK_OK);
int position = scanner().location().beg_pos;
Expression* right = ParseAssignmentExpression(accept_IN, CHECK_OK);
result = new(zone()) BinaryOperation(
isolate(), Token::COMMA, result, right, position);
result =
factory()->NewBinaryOperation(Token::COMMA, result, right, position);
}
return result;
}
@ -2736,7 +2667,7 @@ Expression* Parser::ParseAssignmentExpression(bool accept_IN, bool* ok) {
fni_->Leave();
}
return new(zone()) Assignment(isolate(), op, expression, right, pos);
return factory()->NewAssignment(op, expression, right, pos);
}
@ -2758,8 +2689,8 @@ Expression* Parser::ParseConditionalExpression(bool accept_IN, bool* ok) {
Expect(Token::COLON, CHECK_OK);
int right_position = scanner().peek_location().beg_pos;
Expression* right = ParseAssignmentExpression(accept_IN, CHECK_OK);
return new(zone()) Conditional(
isolate(), expression, left, right, left_position, right_position);
return factory()->NewConditional(
expression, left, right, left_position, right_position);
}
@ -2790,41 +2721,47 @@ Expression* Parser::ParseBinaryExpression(int prec, bool accept_IN, bool* ok) {
switch (op) {
case Token::ADD:
x = NewNumberLiteral(x_val + y_val);
x = factory()->NewNumberLiteral(x_val + y_val);
continue;
case Token::SUB:
x = NewNumberLiteral(x_val - y_val);
x = factory()->NewNumberLiteral(x_val - y_val);
continue;
case Token::MUL:
x = NewNumberLiteral(x_val * y_val);
x = factory()->NewNumberLiteral(x_val * y_val);
continue;
case Token::DIV:
x = NewNumberLiteral(x_val / y_val);
x = factory()->NewNumberLiteral(x_val / y_val);
continue;
case Token::BIT_OR:
x = NewNumberLiteral(DoubleToInt32(x_val) | DoubleToInt32(y_val));
case Token::BIT_OR: {
int value = DoubleToInt32(x_val) | DoubleToInt32(y_val);
x = factory()->NewNumberLiteral(value);
continue;
case Token::BIT_AND:
x = NewNumberLiteral(DoubleToInt32(x_val) & DoubleToInt32(y_val));
}
case Token::BIT_AND: {
int value = DoubleToInt32(x_val) & DoubleToInt32(y_val);
x = factory()->NewNumberLiteral(value);
continue;
case Token::BIT_XOR:
x = NewNumberLiteral(DoubleToInt32(x_val) ^ DoubleToInt32(y_val));
}
case Token::BIT_XOR: {
int value = DoubleToInt32(x_val) ^ DoubleToInt32(y_val);
x = factory()->NewNumberLiteral(value);
continue;
}
case Token::SHL: {
int value = DoubleToInt32(x_val) << (DoubleToInt32(y_val) & 0x1f);
x = NewNumberLiteral(value);
x = factory()->NewNumberLiteral(value);
continue;
}
case Token::SHR: {
uint32_t shift = DoubleToInt32(y_val) & 0x1f;
uint32_t value = DoubleToUint32(x_val) >> shift;
x = NewNumberLiteral(value);
x = factory()->NewNumberLiteral(value);
continue;
}
case Token::SAR: {
uint32_t shift = DoubleToInt32(y_val) & 0x1f;
int value = ArithmeticShiftRight(DoubleToInt32(x_val), shift);
x = NewNumberLiteral(value);
x = factory()->NewNumberLiteral(value);
continue;
}
default:
@ -2843,15 +2780,15 @@ Expression* Parser::ParseBinaryExpression(int prec, bool accept_IN, bool* ok) {
case Token::NE_STRICT: cmp = Token::EQ_STRICT; break;
default: break;
}
x = new(zone()) CompareOperation(isolate(), cmp, x, y, position);
x = factory()->NewCompareOperation(cmp, x, y, position);
if (cmp != op) {
// The comparison was negated - add a NOT.
x = new(zone()) UnaryOperation(isolate(), Token::NOT, x, position);
x = factory()->NewUnaryOperation(Token::NOT, x, position);
}
} else {
// We have a "normal" binary operation.
x = new(zone()) BinaryOperation(isolate(), op, x, y, position);
x = factory()->NewBinaryOperation(op, x, y, position);
}
}
}
@ -2884,7 +2821,7 @@ Expression* Parser::ParseUnaryExpression(bool* ok) {
// Convert the literal to a boolean condition and negate it.
bool condition = literal->ToBoolean()->IsTrue();
Handle<Object> result(isolate()->heap()->ToBoolean(!condition));
return NewLiteral(result);
return factory()->NewLiteral(result);
} else if (literal->IsNumber()) {
// Compute some expressions involving only number literals.
double value = literal->Number();
@ -2892,9 +2829,9 @@ Expression* Parser::ParseUnaryExpression(bool* ok) {
case Token::ADD:
return expression;
case Token::SUB:
return NewNumberLiteral(-value);
return factory()->NewNumberLiteral(-value);
case Token::BIT_NOT:
return NewNumberLiteral(~DoubleToInt32(value));
return factory()->NewNumberLiteral(~DoubleToInt32(value));
default:
break;
}
@ -2911,7 +2848,7 @@ Expression* Parser::ParseUnaryExpression(bool* ok) {
}
}
return new(zone()) UnaryOperation(isolate(), op, expression, position);
return factory()->NewUnaryOperation(op, expression, position);
} else if (Token::IsCountOp(op)) {
op = Next();
@ -2933,11 +2870,10 @@ Expression* Parser::ParseUnaryExpression(bool* ok) {
MarkAsLValue(expression);
int position = scanner().location().beg_pos;
return new(zone()) CountOperation(isolate(),
op,
true /* prefix */,
expression,
position);
return factory()->NewCountOperation(op,
true /* prefix */,
expression,
position);
} else {
return ParsePostfixExpression(ok);
@ -2971,11 +2907,10 @@ Expression* Parser::ParsePostfixExpression(bool* ok) {
Token::Value next = Next();
int position = scanner().location().beg_pos;
expression =
new(zone()) CountOperation(isolate(),
next,
false /* postfix */,
expression,
position);
factory()->NewCountOperation(next,
false /* postfix */,
expression,
position);
}
return expression;
}
@ -2998,7 +2933,7 @@ Expression* Parser::ParseLeftHandSideExpression(bool* ok) {
Consume(Token::LBRACK);
int pos = scanner().location().beg_pos;
Expression* index = ParseExpression(true, CHECK_OK);
result = new(zone()) Property(isolate(), result, index, pos);
result = factory()->NewProperty(result, index, pos);
Expect(Token::RBRACK, CHECK_OK);
break;
}
@ -3031,7 +2966,7 @@ Expression* Parser::ParseLeftHandSideExpression(bool* ok) {
callee->IsVariable(isolate()->factory()->eval_symbol())) {
top_scope_->DeclarationScope()->RecordEvalCall();
}
result = NewCall(result, args, pos);
result = factory()->NewCall(result, args, pos);
break;
}
@ -3039,10 +2974,8 @@ Expression* Parser::ParseLeftHandSideExpression(bool* ok) {
Consume(Token::PERIOD);
int pos = scanner().location().beg_pos;
Handle<String> name = ParseIdentifierName(CHECK_OK);
result = new(zone()) Property(isolate(),
result,
NewLiteral(name),
pos);
result =
factory()->NewProperty(result, factory()->NewLiteral(name), pos);
if (fni_ != NULL) fni_->PushLiteralName(name);
break;
}
@ -3078,10 +3011,8 @@ Expression* Parser::ParseNewPrefix(PositionStack* stack, bool* ok) {
if (!stack->is_empty()) {
int last = stack->pop();
result = new(zone()) CallNew(isolate(),
result,
new(zone()) ZoneList<Expression*>(0),
last);
result = factory()->NewCallNew(
result, new(zone()) ZoneList<Expression*>(0), last);
}
return result;
}
@ -3133,7 +3064,7 @@ Expression* Parser::ParseMemberWithNewPrefixesExpression(PositionStack* stack,
Consume(Token::LBRACK);
int pos = scanner().location().beg_pos;
Expression* index = ParseExpression(true, CHECK_OK);
result = new(zone()) Property(isolate(), result, index, pos);
result = factory()->NewProperty(result, index, pos);
if (fni_ != NULL) {
if (index->IsPropertyName()) {
fni_->PushLiteralName(index->AsLiteral()->AsPropertyName());
@ -3149,10 +3080,8 @@ Expression* Parser::ParseMemberWithNewPrefixesExpression(PositionStack* stack,
Consume(Token::PERIOD);
int pos = scanner().location().beg_pos;
Handle<String> name = ParseIdentifierName(CHECK_OK);
result = new(zone()) Property(isolate(),
result,
NewLiteral(name),
pos);
result =
factory()->NewProperty(result, factory()->NewLiteral(name), pos);
if (fni_ != NULL) fni_->PushLiteralName(name);
break;
}
@ -3161,7 +3090,7 @@ Expression* Parser::ParseMemberWithNewPrefixesExpression(PositionStack* stack,
// Consume one of the new prefixes (already parsed).
ZoneList<Expression*>* args = ParseArguments(CHECK_OK);
int last = stack->pop();
result = new(zone()) CallNew(isolate(), result, args, last);
result = factory()->NewCallNew(result, args, last);
break;
}
default:
@ -3180,7 +3109,7 @@ DebuggerStatement* Parser::ParseDebuggerStatement(bool* ok) {
Expect(Token::DEBUGGER, CHECK_OK);
ExpectSemicolon(CHECK_OK);
return new(zone()) DebuggerStatement();
return factory()->NewDebuggerStatement();
}
@ -3245,33 +3174,31 @@ Expression* Parser::ParsePrimaryExpression(bool* ok) {
switch (peek()) {
case Token::THIS: {
Consume(Token::THIS);
result = new(zone()) VariableProxy(isolate(), top_scope_->receiver());
result = factory()->NewVariableProxy(top_scope_->receiver());
break;
}
case Token::NULL_LITERAL:
Consume(Token::NULL_LITERAL);
result = new(zone()) Literal(
isolate(), isolate()->factory()->null_value());
result = factory()->NewLiteral(isolate()->factory()->null_value());
break;
case Token::TRUE_LITERAL:
Consume(Token::TRUE_LITERAL);
result = new(zone()) Literal(
isolate(), isolate()->factory()->true_value());
result = factory()->NewLiteral(isolate()->factory()->true_value());
break;
case Token::FALSE_LITERAL:
Consume(Token::FALSE_LITERAL);
result = new(zone()) Literal(
isolate(), isolate()->factory()->false_value());
result = factory()->NewLiteral(isolate()->factory()->false_value());
break;
case Token::IDENTIFIER:
case Token::FUTURE_STRICT_RESERVED_WORD: {
Handle<String> name = ParseIdentifier(CHECK_OK);
if (fni_ != NULL) fni_->PushVariableName(name);
result = top_scope_->NewUnresolved(name, scanner().location().beg_pos);
result = top_scope_->NewUnresolved(
factory(), name, scanner().location().beg_pos);
break;
}
@ -3281,14 +3208,14 @@ Expression* Parser::ParsePrimaryExpression(bool* ok) {
double value = StringToDouble(isolate()->unicode_cache(),
scanner().literal_ascii_string(),
ALLOW_HEX | ALLOW_OCTALS);
result = NewNumberLiteral(value);
result = factory()->NewNumberLiteral(value);
break;
}
case Token::STRING: {
Consume(Token::STRING);
Handle<String> symbol = GetSymbol(CHECK_OK);
result = NewLiteral(symbol);
result = factory()->NewLiteral(symbol);
if (fni_ != NULL) fni_->PushLiteralName(symbol);
break;
}
@ -3482,8 +3409,8 @@ Expression* Parser::ParseArrayLiteral(bool* ok) {
literals->set(0, Smi::FromInt(elements_kind));
literals->set(1, *element_values);
return new(zone()) ArrayLiteral(
isolate(), literals, values, literal_index, is_simple, depth);
return factory()->NewArrayLiteral(
literals, values, literal_index, is_simple, depth);
}
@ -3760,9 +3687,7 @@ ObjectLiteral::Property* Parser::ParseObjectLiteralGetSet(bool is_getter,
CHECK_OK);
// Allow any number of parameters for compatibilty with JSC.
// Specification only allows zero parameters for get and one for set.
ObjectLiteral::Property* property =
new(zone()) ObjectLiteral::Property(is_getter, value);
return property;
return factory()->NewObjectLiteralProperty(is_getter, value);
} else {
ReportUnexpectedToken(next);
*ok = false;
@ -3827,7 +3752,7 @@ Expression* Parser::ParseObjectLiteral(bool* ok) {
}
// Failed to parse as get/set property, so it's just a property
// called "get" or "set".
key = NewLiteral(id);
key = factory()->NewLiteral(id);
break;
}
case Token::STRING: {
@ -3836,10 +3761,10 @@ Expression* Parser::ParseObjectLiteral(bool* ok) {
if (fni_ != NULL) fni_->PushLiteralName(string);
uint32_t index;
if (!string.is_null() && string->AsArrayIndex(&index)) {
key = NewNumberLiteral(index);
key = factory()->NewNumberLiteral(index);
break;
}
key = NewLiteral(string);
key = factory()->NewLiteral(string);
break;
}
case Token::NUMBER: {
@ -3848,14 +3773,14 @@ Expression* Parser::ParseObjectLiteral(bool* ok) {
double value = StringToDouble(isolate()->unicode_cache(),
scanner().literal_ascii_string(),
ALLOW_HEX | ALLOW_OCTALS);
key = NewNumberLiteral(value);
key = factory()->NewNumberLiteral(value);
break;
}
default:
if (Token::IsKeyword(next)) {
Consume(next);
Handle<String> string = GetSymbol(CHECK_OK);
key = NewLiteral(string);
key = factory()->NewLiteral(string);
} else {
// Unexpected token.
Token::Value next = Next();
@ -3910,14 +3835,13 @@ Expression* Parser::ParseObjectLiteral(bool* ok) {
&is_simple,
&fast_elements,
&depth);
return new(zone()) ObjectLiteral(isolate(),
constant_properties,
properties,
literal_index,
is_simple,
fast_elements,
depth,
has_function);
return factory()->NewObjectLiteral(constant_properties,
properties,
literal_index,
is_simple,
fast_elements,
depth,
has_function);
}
@ -3936,8 +3860,7 @@ Expression* Parser::ParseRegExpLiteral(bool seen_equal, bool* ok) {
Handle<String> js_flags = NextLiteralString(TENURED);
Next();
return new(zone()) RegExpLiteral(
isolate(), js_pattern, js_flags, literal_index);
return factory()->NewRegExpLiteral(js_pattern, js_flags, literal_index);
}
@ -3968,7 +3891,7 @@ ZoneList<Expression*>* Parser::ParseArguments(bool* ok) {
class SingletonLogger : public ParserRecorder {
public:
SingletonLogger() : has_error_(false), start_(-1), end_(-1) { }
~SingletonLogger() { }
virtual ~SingletonLogger() { }
void Reset() { has_error_ = false; }
@ -4089,6 +4012,7 @@ FunctionLiteral* Parser::ParseFunctionLiteral(Handle<String> function_name,
bool only_simple_this_property_assignments;
Handle<FixedArray> this_property_assignments;
bool has_duplicate_parameters = false;
AstProperties ast_properties;
// Parse function body.
{ FunctionState function_state(this, scope, isolate());
top_scope_->SetScopeName(function_name);
@ -4151,7 +4075,8 @@ FunctionLiteral* Parser::ParseFunctionLiteral(Handle<String> function_name,
} else {
fvar_mode = CONST;
}
fvar = top_scope_->DeclareFunctionVar(function_name, fvar_mode);
fvar =
top_scope_->DeclareFunctionVar(function_name, fvar_mode, factory());
}
// Determine whether the function will be lazily compiled.
@ -4238,14 +4163,14 @@ FunctionLiteral* Parser::ParseFunctionLiteral(Handle<String> function_name,
if (!is_lazily_compiled) {
body = new(zone()) ZoneList<Statement*>(8);
if (fvar != NULL) {
VariableProxy* fproxy = top_scope_->NewUnresolved(function_name);
VariableProxy* fproxy =
top_scope_->NewUnresolved(factory(), function_name);
fproxy->BindTo(fvar);
body->Add(new(zone()) ExpressionStatement(
new(zone()) Assignment(isolate(),
fvar_init_op,
fproxy,
new(zone()) ThisFunction(isolate()),
RelocInfo::kNoPosition)));
body->Add(factory()->NewExpressionStatement(
factory()->NewAssignment(fvar_init_op,
fproxy,
factory()->NewThisFunction(),
RelocInfo::kNoPosition)));
}
ParseSourceElements(body, Token::RBRACE, CHECK_OK);
@ -4306,6 +4231,7 @@ FunctionLiteral* Parser::ParseFunctionLiteral(Handle<String> function_name,
scope->end_position(),
CHECK_OK);
}
ast_properties = *factory()->visitor()->ast_properties();
}
if (is_extended_mode()) {
@ -4313,19 +4239,20 @@ FunctionLiteral* Parser::ParseFunctionLiteral(Handle<String> function_name,
}
FunctionLiteral* function_literal =
new(zone()) FunctionLiteral(isolate(),
function_name,
scope,
body,
materialized_literal_count,
expected_property_count,
handler_count,
only_simple_this_property_assignments,
this_property_assignments,
num_parameters,
type,
has_duplicate_parameters);
factory()->NewFunctionLiteral(function_name,
scope,
body,
materialized_literal_count,
expected_property_count,
handler_count,
only_simple_this_property_assignments,
this_property_assignments,
num_parameters,
has_duplicate_parameters,
type,
true);
function_literal->set_function_token_position(function_token_position);
function_literal->set_ast_properties(&ast_properties);
if (fni_ != NULL && should_infer_name) fni_->AddFunction(function_literal);
return function_literal;
@ -4395,7 +4322,7 @@ Expression* Parser::ParseV8Intrinsic(bool* ok) {
}
// We have a valid intrinsics call or a call to a builtin.
return new(zone()) CallRuntime(isolate(), name, function, args);
return factory()->NewCallRuntime(name, function, args);
}
@ -4451,17 +4378,12 @@ void Parser::ExpectSemicolon(bool* ok) {
Literal* Parser::GetLiteralUndefined() {
return NewLiteral(isolate()->factory()->undefined_value());
return factory()->NewLiteral(isolate()->factory()->undefined_value());
}
Literal* Parser::GetLiteralTheHole() {
return NewLiteral(isolate()->factory()->the_hole_value());
}
Literal* Parser::GetLiteralNumber(double value) {
return NewNumberLiteral(value);
return factory()->NewLiteral(isolate()->factory()->the_hole_value());
}
@ -4639,11 +4561,6 @@ void Parser::RegisterTargetUse(Label* target, Target* stop) {
}
Literal* Parser::NewNumberLiteral(double number) {
return NewLiteral(isolate()->factory()->NewNumber(number, TENURED));
}
Expression* Parser::NewThrowReferenceError(Handle<String> type) {
return NewThrowError(isolate()->factory()->MakeReferenceError_symbol(),
type, HandleVector<Object>(NULL, 0));
@ -4687,15 +4604,11 @@ Expression* Parser::NewThrowError(Handle<String> constructor,
elements, FAST_ELEMENTS, TENURED);
ZoneList<Expression*>* args = new(zone()) ZoneList<Expression*>(2);
args->Add(NewLiteral(type));
args->Add(NewLiteral(array));
CallRuntime* call_constructor = new(zone()) CallRuntime(isolate(),
constructor,
NULL,
args);
return new(zone()) Throw(isolate(),
call_constructor,
scanner().location().beg_pos);
args->Add(factory()->NewLiteral(type));
args->Add(factory()->NewLiteral(array));
CallRuntime* call_constructor =
factory()->NewCallRuntime(constructor, NULL, args);
return factory()->NewThrow(call_constructor, scanner().location().beg_pos);
}
// ----------------------------------------------------------------------------
@ -5667,7 +5580,7 @@ bool ParserApi::Parse(CompilationInfo* info, int parsing_flags) {
parsing_flags |= EXTENDED_MODE;
}
if (FLAG_allow_natives_syntax || info->is_native()) {
// We requre %identifier(..) syntax.
// We require %identifier(..) syntax.
parsing_flags |= kAllowNativesSyntax;
}
if (info->is_lazy()) {

View File

@ -1,4 +1,4 @@
// Copyright 2011 the V8 project authors. All rights reserved.
// Copyright 2012 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:
@ -435,9 +435,8 @@ class Parser {
v8::Extension* extension,
ScriptDataImpl* pre_data);
virtual ~Parser() {
if (reusable_preparser_ != NULL) {
delete reusable_preparser_;
}
delete reusable_preparser_;
reusable_preparser_ = NULL;
}
// Returns NULL if parsing failed.
@ -477,7 +476,69 @@ class Parser {
};
class BlockState;
class FunctionState;
class FunctionState BASE_EMBEDDED {
public:
FunctionState(Parser* parser,
Scope* scope,
Isolate* isolate);
~FunctionState();
int NextMaterializedLiteralIndex() {
return next_materialized_literal_index_++;
}
int materialized_literal_count() {
return next_materialized_literal_index_ - JSFunction::kLiteralsPrefixSize;
}
int NextHandlerIndex() { return next_handler_index_++; }
int handler_count() { return next_handler_index_; }
void SetThisPropertyAssignmentInfo(
bool only_simple_this_property_assignments,
Handle<FixedArray> this_property_assignments) {
only_simple_this_property_assignments_ =
only_simple_this_property_assignments;
this_property_assignments_ = this_property_assignments;
}
bool only_simple_this_property_assignments() {
return only_simple_this_property_assignments_;
}
Handle<FixedArray> this_property_assignments() {
return this_property_assignments_;
}
void AddProperty() { expected_property_count_++; }
int expected_property_count() { return expected_property_count_; }
AstNodeFactory<AstConstructionVisitor>* factory() { return &factory_; }
private:
// Used to assign an index to each literal that needs materialization in
// the function. Includes regexp literals, and boilerplate for object and
// array literals.
int next_materialized_literal_index_;
// Used to assign a per-function index to try and catch handlers.
int next_handler_index_;
// Properties count estimation.
int expected_property_count_;
// Keeps track of assignments to properties of this. Used for
// optimizing constructors.
bool only_simple_this_property_assignments_;
Handle<FixedArray> this_property_assignments_;
Parser* parser_;
FunctionState* outer_function_state_;
Scope* outer_scope_;
int saved_ast_node_id_;
AstNodeFactory<AstConstructionVisitor> factory_;
};
FunctionLiteral* ParseLazy(CompilationInfo* info,
UC16CharacterStream* source,
@ -651,7 +712,6 @@ class Parser {
// Get odd-ball literals.
Literal* GetLiteralUndefined();
Literal* GetLiteralTheHole();
Literal* GetLiteralNumber(double value);
Handle<String> ParseIdentifier(bool* ok);
Handle<String> ParseIdentifierOrStrictReservedWord(
@ -699,31 +759,12 @@ class Parser {
// Factory methods.
Statement* EmptyStatement() {
static v8::internal::EmptyStatement* empty =
::new v8::internal::EmptyStatement();
return empty;
}
Scope* NewScope(Scope* parent, ScopeType type);
Handle<String> LookupSymbol(int symbol_id);
Handle<String> LookupCachedSymbol(int symbol_id);
Expression* NewCall(Expression* expression,
ZoneList<Expression*>* arguments,
int pos) {
return new(zone()) Call(isolate(), expression, arguments, pos);
}
inline Literal* NewLiteral(Handle<Object> handle) {
return new(zone()) Literal(isolate(), handle);
}
// Create a number literal.
Literal* NewNumberLiteral(double value);
// Generate AST node that throw a ReferenceError with the given type.
Expression* NewThrowReferenceError(Handle<String> type);
@ -746,6 +787,10 @@ class Parser {
preparser::PreParser::PreParseResult LazyParseFunctionLiteral(
SingletonLogger* logger);
AstNodeFactory<AstConstructionVisitor>* factory() {
return current_function_state_->factory();
}
Isolate* isolate_;
ZoneList<Handle<String> > symbol_cache_;

View File

@ -1,4 +1,4 @@
// Copyright 2011 the V8 project authors. All rights reserved.
// Copyright 2012 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:
@ -42,12 +42,18 @@ class Processor: public AstVisitor {
: result_(result),
result_assigned_(false),
is_set_(false),
in_try_(false) {
}
in_try_(false),
factory_(isolate()) { }
virtual ~Processor() { }
void Process(ZoneList<Statement*>* statements);
bool result_assigned() const { return result_assigned_; }
AstNodeFactory<AstNullVisitor>* factory() {
return &factory_;
}
private:
Variable* result_;
@ -64,15 +70,13 @@ class Processor: public AstVisitor {
bool is_set_;
bool in_try_;
AstNodeFactory<AstNullVisitor> factory_;
Expression* SetResult(Expression* value) {
result_assigned_ = true;
Zone* zone = isolate()->zone();
VariableProxy* result_proxy = new(zone) VariableProxy(isolate(), result_);
return new(zone) Assignment(isolate(),
Token::ASSIGN,
result_proxy,
value,
RelocInfo::kNoPosition);
VariableProxy* result_proxy = factory()->NewVariableProxy(result_);
return factory()->NewAssignment(
Token::ASSIGN, result_proxy, value, RelocInfo::kNoPosition);
}
// Node visitors.
@ -237,8 +241,6 @@ bool Rewriter::Rewrite(CompilationInfo* info) {
if (processor.result_assigned()) {
ASSERT(function->end_position() != RelocInfo::kNoPosition);
Isolate* isolate = info->isolate();
Zone* zone = isolate->zone();
// Set the position of the assignment statement one character past the
// source code, such that it definitely is not in the source code range
// of an immediate inner scope. For example in
@ -246,10 +248,11 @@ bool Rewriter::Rewrite(CompilationInfo* info) {
// the end position of the function generated for executing the eval code
// coincides with the end of the with scope which is the position of '1'.
int position = function->end_position();
VariableProxy* result_proxy = new(zone) VariableProxy(
isolate, result->name(), false, position);
VariableProxy* result_proxy = processor.factory()->NewVariableProxy(
result->name(), false, position);
result_proxy->BindTo(result);
Statement* result_statement = new(zone) ReturnStatement(result_proxy);
Statement* result_statement =
processor.factory()->NewReturnStatement(result_proxy);
result_statement->set_statement_pos(position);
body->Add(result_statement);
}

View File

@ -1,4 +1,4 @@
// Copyright 2011 the V8 project authors. All rights reserved.
// Copyright 2012 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:
@ -272,8 +272,11 @@ bool Scope::Analyze(CompilationInfo* info) {
top = top->outer_scope();
}
// Allocated the variables.
top->AllocateVariables(info->global_scope());
// Allocate the variables.
{
AstNodeFactory<AstNullVisitor> ast_node_factory(info->isolate());
top->AllocateVariables(info->global_scope(), &ast_node_factory);
}
#ifdef DEBUG
if (info->isolate()->bootstrapper()->IsActive()
@ -415,7 +418,8 @@ Variable* Scope::LocalLookup(Handle<String> name) {
}
Variable* Scope::LookupFunctionVar(Handle<String> name) {
Variable* Scope::LookupFunctionVar(Handle<String> name,
AstNodeFactory<AstNullVisitor>* factory) {
if (function_ != NULL && function_->name().is_identical_to(name)) {
return function_->var();
} else if (!scope_info_.is_null()) {
@ -423,7 +427,7 @@ Variable* Scope::LookupFunctionVar(Handle<String> name) {
VariableMode mode;
int index = scope_info_->FunctionContextSlotIndex(*name, &mode);
if (index < 0) return NULL;
Variable* var = DeclareFunctionVar(name, mode);
Variable* var = DeclareFunctionVar(name, mode, factory);
var->AllocateTo(Variable::CONTEXT, index);
return var;
} else {
@ -443,15 +447,6 @@ Variable* Scope::Lookup(Handle<String> name) {
}
Variable* Scope::DeclareFunctionVar(Handle<String> name, VariableMode mode) {
ASSERT(is_function_scope() && function_ == NULL);
Variable* function_var = new Variable(
this, name, mode, true, Variable::NORMAL, kCreatedInitialized);
function_ = new(isolate_->zone()) VariableProxy(isolate_, function_var);
return function_var;
}
void Scope::DeclareParameter(Handle<String> name, VariableMode mode) {
ASSERT(!already_resolved());
ASSERT(is_function_scope());
@ -489,18 +484,6 @@ Variable* Scope::DeclareGlobal(Handle<String> name) {
}
VariableProxy* Scope::NewUnresolved(Handle<String> name, int position) {
// Note that we must not share the unresolved variables with
// the same name because they may be removed selectively via
// RemoveUnresolved().
ASSERT(!already_resolved());
VariableProxy* proxy = new(isolate_->zone()) VariableProxy(
isolate_, name, false, position);
unresolved_.Add(proxy);
return proxy;
}
void Scope::RemoveUnresolved(VariableProxy* var) {
// Most likely (always?) any variable we want to remove
// was just added before, so we search backwards.
@ -623,7 +606,8 @@ void Scope::CollectStackAndContextLocals(ZoneList<Variable*>* stack_locals,
}
void Scope::AllocateVariables(Scope* global_scope) {
void Scope::AllocateVariables(Scope* global_scope,
AstNodeFactory<AstNullVisitor>* factory) {
// 1) Propagate scope information.
bool outer_scope_calls_non_strict_eval = false;
if (outer_scope_ != NULL) {
@ -634,7 +618,7 @@ void Scope::AllocateVariables(Scope* global_scope) {
PropagateScopeInfo(outer_scope_calls_non_strict_eval);
// 2) Resolve variables.
ResolveVariablesRecursively(global_scope);
ResolveVariablesRecursively(global_scope, factory);
// 3) Allocate variables.
AllocateVariablesRecursively();
@ -897,7 +881,8 @@ Variable* Scope::NonLocal(Handle<String> name, VariableMode mode) {
Variable* Scope::LookupRecursive(Handle<String> name,
BindingKind* binding_kind) {
BindingKind* binding_kind,
AstNodeFactory<AstNullVisitor>* factory) {
ASSERT(binding_kind != NULL);
// Try to find the variable in this scope.
Variable* var = LocalLookup(name);
@ -914,11 +899,11 @@ Variable* Scope::LookupRecursive(Handle<String> name,
// if any. We can do this for all scopes, since the function variable is
// only present - if at all - for function scopes.
*binding_kind = UNBOUND;
var = LookupFunctionVar(name);
var = LookupFunctionVar(name, factory);
if (var != NULL) {
*binding_kind = BOUND;
} else if (outer_scope_ != NULL) {
var = outer_scope_->LookupRecursive(name, binding_kind);
var = outer_scope_->LookupRecursive(name, binding_kind, factory);
if (*binding_kind == BOUND && (is_function_scope() || is_with_scope())) {
var->ForceContextAllocation();
}
@ -951,7 +936,8 @@ Variable* Scope::LookupRecursive(Handle<String> name,
void Scope::ResolveVariable(Scope* global_scope,
VariableProxy* proxy) {
VariableProxy* proxy,
AstNodeFactory<AstNullVisitor>* factory) {
ASSERT(global_scope == NULL || global_scope->is_global_scope());
// If the proxy is already resolved there's nothing to do
@ -960,7 +946,7 @@ void Scope::ResolveVariable(Scope* global_scope,
// Otherwise, try to resolve the variable.
BindingKind binding_kind;
Variable* var = LookupRecursive(proxy->name(), &binding_kind);
Variable* var = LookupRecursive(proxy->name(), &binding_kind, factory);
switch (binding_kind) {
case BOUND:
// We found a variable binding.
@ -1001,17 +987,19 @@ void Scope::ResolveVariable(Scope* global_scope,
}
void Scope::ResolveVariablesRecursively(Scope* global_scope) {
void Scope::ResolveVariablesRecursively(
Scope* global_scope,
AstNodeFactory<AstNullVisitor>* factory) {
ASSERT(global_scope == NULL || global_scope->is_global_scope());
// Resolve unresolved variables for this scope.
for (int i = 0; i < unresolved_.length(); i++) {
ResolveVariable(global_scope, unresolved_[i]);
ResolveVariable(global_scope, unresolved_[i], factory);
}
// Resolve unresolved variables for inner scopes.
for (int i = 0; i < inner_scopes_.length(); i++) {
inner_scopes_[i]->ResolveVariablesRecursively(global_scope);
inner_scopes_[i]->ResolveVariablesRecursively(global_scope, factory);
}
}

View File

@ -1,4 +1,4 @@
// Copyright 2011 the V8 project authors. All rights reserved.
// Copyright 2012 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:
@ -115,7 +115,8 @@ class Scope: public ZoneObject {
// between this scope and the outer scope. (ECMA-262, 3rd., requires that
// the name of named function literal is kept in an intermediate scope
// in between this scope and the next outer scope.)
Variable* LookupFunctionVar(Handle<String> name);
Variable* LookupFunctionVar(Handle<String> name,
AstNodeFactory<AstNullVisitor>* factory);
// Lookup a variable in this scope or outer scopes.
// Returns the variable or NULL if not found.
@ -124,7 +125,16 @@ class Scope: public ZoneObject {
// Declare the function variable for a function literal. This variable
// is in an intermediate scope between this function scope and the the
// outer scope. Only possible for function scopes; at most one variable.
Variable* DeclareFunctionVar(Handle<String> name, VariableMode mode);
template<class Visitor>
Variable* DeclareFunctionVar(Handle<String> name,
VariableMode mode,
AstNodeFactory<Visitor>* factory) {
ASSERT(is_function_scope() && function_ == NULL);
Variable* function_var = new Variable(
this, name, mode, true, Variable::NORMAL, kCreatedInitialized);
function_ = factory->NewVariableProxy(function_var);
return function_var;
}
// Declare a parameter in this scope. When there are duplicated
// parameters the rightmost one 'wins'. However, the implementation
@ -144,8 +154,18 @@ class Scope: public ZoneObject {
Variable* DeclareGlobal(Handle<String> name);
// Create a new unresolved variable.
VariableProxy* NewUnresolved(Handle<String> name,
int position = RelocInfo::kNoPosition);
template<class Visitor>
VariableProxy* NewUnresolved(AstNodeFactory<Visitor>* factory,
Handle<String> name,
int position = RelocInfo::kNoPosition) {
// Note that we must not share the unresolved variables with
// the same name because they may be removed selectively via
// RemoveUnresolved().
ASSERT(!already_resolved());
VariableProxy* proxy = factory->NewVariableProxy(name, false, position);
unresolved_.Add(proxy);
return proxy;
}
// Remove a unresolved variable. During parsing, an unresolved variable
// may have been added optimistically, but then only the variable name
@ -332,7 +352,8 @@ class Scope: public ZoneObject {
// In the case of code compiled and run using 'eval', the context
// parameter is the context in which eval was called. In all other
// cases the context parameter is an empty handle.
void AllocateVariables(Scope* global_scope);
void AllocateVariables(Scope* global_scope,
AstNodeFactory<AstNullVisitor>* factory);
// Current number of var or const locals.
int num_var_or_const() { return num_var_or_const_; }
@ -519,10 +540,13 @@ class Scope: public ZoneObject {
// scope. If the code is executed because of a call to 'eval', the context
// parameter should be set to the calling context of 'eval'.
Variable* LookupRecursive(Handle<String> name,
BindingKind* binding_kind);
BindingKind* binding_kind,
AstNodeFactory<AstNullVisitor>* factory);
void ResolveVariable(Scope* global_scope,
VariableProxy* proxy);
void ResolveVariablesRecursively(Scope* global_scope);
VariableProxy* proxy,
AstNodeFactory<AstNullVisitor>* factory);
void ResolveVariablesRecursively(Scope* global_scope,
AstNodeFactory<AstNullVisitor>* factory);
// Scope analysis.
bool PropagateScopeInfo(bool outer_scope_calls_non_strict_eval);

View File

@ -1,4 +1,4 @@
// Copyright 2006-2008 the V8 project authors. All rights reserved.
// Copyright 2012 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:
@ -40,7 +40,8 @@ TEST(List) {
CHECK_EQ(0, list->length());
ZoneScope zone_scope(Isolate::Current(), DELETE_ON_EXIT);
AstNode* node = new(ZONE) EmptyStatement();
AstNodeFactory<AstNullVisitor> factory(Isolate::Current());
AstNode* node = factory.NewEmptyStatement();
list->Add(node);
CHECK_EQ(1, list->length());
CHECK_EQ(node, list->at(0));