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
parent 9463c00d
This diff is collapsed.
This diff is collapsed.
// 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));
}
......
......@@ -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);
......
......@@ -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.
......
......@@ -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) \
......
......@@ -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);
......
......@@ -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
};
......
This diff is collapsed.
// 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_;
......
// 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);
}
......
// 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);
}
}
......
// 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);
......
// 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));
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment