summaryrefslogtreecommitdiff
path: root/deps/v8/src/parser.cc
diff options
context:
space:
mode:
Diffstat (limited to 'deps/v8/src/parser.cc')
-rw-r--r--deps/v8/src/parser.cc232
1 files changed, 117 insertions, 115 deletions
diff --git a/deps/v8/src/parser.cc b/deps/v8/src/parser.cc
index e8d1810616..fb94a1a60b 100644
--- a/deps/v8/src/parser.cc
+++ b/deps/v8/src/parser.cc
@@ -587,7 +587,7 @@ Parser::Parser(Handle<Script> script,
fni_(NULL),
stack_overflow_(false),
parenthesized_function_(false),
- harmony_block_scoping_(false) {
+ harmony_scoping_(false) {
AstNode::ResetIds();
}
@@ -650,7 +650,7 @@ FunctionLiteral* Parser::DoParseProgram(Handle<String> source,
CheckOctalLiteral(beg_loc, scanner().location().end_pos, &ok);
}
- if (ok && harmony_block_scoping_) {
+ if (ok && harmony_scoping_) {
CheckConflictingVarDeclarations(scope, &ok);
}
@@ -817,9 +817,9 @@ void Parser::ReportMessageAt(Scanner::Location source_location,
isolate()->Throw(*result, &location);
}
-void Parser::SetHarmonyBlockScoping(bool block_scoping) {
- scanner().SetHarmonyBlockScoping(block_scoping);
- harmony_block_scoping_ = block_scoping;
+void Parser::SetHarmonyScoping(bool block_scoping) {
+ scanner().SetHarmonyScoping(block_scoping);
+ harmony_scoping_ = block_scoping;
}
// Base class containing common code for the different finder classes used by
@@ -957,17 +957,18 @@ class InitializationBlockFinder : public ParserFinder {
};
-// A ThisNamedPropertyAssigmentFinder finds and marks statements of the form
+// A ThisNamedPropertyAssignmentFinder finds and marks statements of the form
// this.x = ...;, where x is a named property. It also determines whether a
// function contains only assignments of this type.
-class ThisNamedPropertyAssigmentFinder : public ParserFinder {
+class ThisNamedPropertyAssignmentFinder : public ParserFinder {
public:
- explicit ThisNamedPropertyAssigmentFinder(Isolate* isolate)
+ explicit ThisNamedPropertyAssignmentFinder(Isolate* isolate)
: isolate_(isolate),
only_simple_this_property_assignments_(true),
- names_(NULL),
- assigned_arguments_(NULL),
- assigned_constants_(NULL) {}
+ names_(0),
+ assigned_arguments_(0),
+ assigned_constants_(0) {
+ }
void Update(Scope* scope, Statement* stat) {
// Bail out if function already has property assignment that are
@@ -994,19 +995,17 @@ class ThisNamedPropertyAssigmentFinder : public ParserFinder {
// Returns a fixed array containing three elements for each assignment of the
// form this.x = y;
Handle<FixedArray> GetThisPropertyAssignments() {
- if (names_ == NULL) {
+ if (names_.is_empty()) {
return isolate_->factory()->empty_fixed_array();
}
- ASSERT(names_ != NULL);
- ASSERT(assigned_arguments_ != NULL);
- ASSERT_EQ(names_->length(), assigned_arguments_->length());
- ASSERT_EQ(names_->length(), assigned_constants_->length());
+ ASSERT_EQ(names_.length(), assigned_arguments_.length());
+ ASSERT_EQ(names_.length(), assigned_constants_.length());
Handle<FixedArray> assignments =
- isolate_->factory()->NewFixedArray(names_->length() * 3);
- for (int i = 0; i < names_->length(); i++) {
- assignments->set(i * 3, *names_->at(i));
- assignments->set(i * 3 + 1, Smi::FromInt(assigned_arguments_->at(i)));
- assignments->set(i * 3 + 2, *assigned_constants_->at(i));
+ isolate_->factory()->NewFixedArray(names_.length() * 3);
+ for (int i = 0; i < names_.length(); ++i) {
+ assignments->set(i * 3, *names_[i]);
+ assignments->set(i * 3 + 1, Smi::FromInt(assigned_arguments_[i]));
+ assignments->set(i * 3 + 2, *assigned_constants_[i]);
}
return assignments;
}
@@ -1063,18 +1062,37 @@ class ThisNamedPropertyAssigmentFinder : public ParserFinder {
AssignmentFromSomethingElse();
}
+
+
+
+ // We will potentially reorder the property assignments, so they must be
+ // simple enough that the ordering does not matter.
void AssignmentFromParameter(Handle<String> name, int index) {
- EnsureAllocation();
- names_->Add(name);
- assigned_arguments_->Add(index);
- assigned_constants_->Add(isolate_->factory()->undefined_value());
+ EnsureInitialized();
+ for (int i = 0; i < names_.length(); ++i) {
+ if (name->Equals(*names_[i])) {
+ assigned_arguments_[i] = index;
+ assigned_constants_[i] = isolate_->factory()->undefined_value();
+ return;
+ }
+ }
+ names_.Add(name);
+ assigned_arguments_.Add(index);
+ assigned_constants_.Add(isolate_->factory()->undefined_value());
}
void AssignmentFromConstant(Handle<String> name, Handle<Object> value) {
- EnsureAllocation();
- names_->Add(name);
- assigned_arguments_->Add(-1);
- assigned_constants_->Add(value);
+ EnsureInitialized();
+ for (int i = 0; i < names_.length(); ++i) {
+ if (name->Equals(*names_[i])) {
+ assigned_arguments_[i] = -1;
+ assigned_constants_[i] = value;
+ return;
+ }
+ }
+ names_.Add(name);
+ assigned_arguments_.Add(-1);
+ assigned_constants_.Add(value);
}
void AssignmentFromSomethingElse() {
@@ -1082,35 +1100,36 @@ class ThisNamedPropertyAssigmentFinder : public ParserFinder {
only_simple_this_property_assignments_ = false;
}
- void EnsureAllocation() {
- if (names_ == NULL) {
- ASSERT(assigned_arguments_ == NULL);
- ASSERT(assigned_constants_ == NULL);
- Zone* zone = isolate_->zone();
- names_ = new(zone) ZoneStringList(4);
- assigned_arguments_ = new(zone) ZoneList<int>(4);
- assigned_constants_ = new(zone) ZoneObjectList(4);
+ void EnsureInitialized() {
+ if (names_.capacity() == 0) {
+ ASSERT(assigned_arguments_.capacity() == 0);
+ ASSERT(assigned_constants_.capacity() == 0);
+ names_.Initialize(4);
+ assigned_arguments_.Initialize(4);
+ assigned_constants_.Initialize(4);
}
}
Isolate* isolate_;
bool only_simple_this_property_assignments_;
- ZoneStringList* names_;
- ZoneList<int>* assigned_arguments_;
- ZoneObjectList* assigned_constants_;
+ ZoneStringList names_;
+ ZoneList<int> assigned_arguments_;
+ ZoneObjectList assigned_constants_;
};
Statement* Parser::ParseSourceElement(ZoneStringList* labels,
bool* ok) {
+ // (Ecma 262 5th Edition, clause 14):
+ // SourceElement:
+ // Statement
+ // FunctionDeclaration
+ //
+ // In harmony mode we allow additionally the following productions
+ // SourceElement:
+ // LetDeclaration
+
if (peek() == Token::FUNCTION) {
- // FunctionDeclaration is only allowed in the context of SourceElements
- // (Ecma 262 5th Edition, clause 14):
- // SourceElement:
- // Statement
- // FunctionDeclaration
- // Common language extension is to allow function declaration in place
- // of any statement. This language extension is disabled in strict mode.
return ParseFunctionDeclaration(ok);
} else if (peek() == Token::LET) {
return ParseVariableStatement(kSourceElement, ok);
@@ -1124,7 +1143,7 @@ void* Parser::ParseSourceElements(ZoneList<Statement*>* processor,
int end_token,
bool* ok) {
// SourceElements ::
- // (Statement)* <end_token>
+ // (SourceElement)* <end_token>
// Allocate a target stack to use for this set of source
// elements. This way, all scripts and functions get their own
@@ -1134,7 +1153,7 @@ void* Parser::ParseSourceElements(ZoneList<Statement*>* processor,
ASSERT(processor != NULL);
InitializationBlockFinder block_finder(top_scope_, target_stack_);
- ThisNamedPropertyAssigmentFinder this_property_assignment_finder(isolate());
+ ThisNamedPropertyAssignmentFinder this_property_assignment_finder(isolate());
bool directive_prologue = true; // Parsing directive prologue.
while (peek() != end_token) {
@@ -1295,8 +1314,13 @@ Statement* Parser::ParseStatement(ZoneStringList* labels, bool* ok) {
}
case Token::FUNCTION: {
- // In strict mode, FunctionDeclaration is only allowed in the context
- // of SourceElements.
+ // FunctionDeclaration is only allowed in the context of SourceElements
+ // (Ecma 262 5th Edition, clause 14):
+ // SourceElement:
+ // Statement
+ // FunctionDeclaration
+ // Common language extension is to allow function declaration in place
+ // of any statement. This language extension is disabled in strict mode.
if (top_scope_->is_strict_mode()) {
ReportMessageAt(scanner().peek_location(), "strict_function",
Vector<const char*>::empty());
@@ -1321,7 +1345,7 @@ Statement* Parser::ParseStatement(ZoneStringList* labels, bool* ok) {
VariableProxy* Parser::Declare(Handle<String> name,
- Variable::Mode mode,
+ VariableMode mode,
FunctionLiteral* fun,
bool resolve,
bool* ok) {
@@ -1339,7 +1363,7 @@ VariableProxy* Parser::Declare(Handle<String> name,
// Similarly, strict mode eval scope does not leak variable declarations to
// the caller's scope so we declare all locals, too.
- Scope* declaration_scope = mode == Variable::LET ? top_scope_
+ Scope* declaration_scope = mode == LET ? top_scope_
: top_scope_->DeclarationScope();
if (declaration_scope->is_function_scope() ||
declaration_scope->is_strict_mode_eval_scope() ||
@@ -1361,12 +1385,12 @@ VariableProxy* Parser::Declare(Handle<String> name,
//
// because the var declaration is hoisted to the function scope where 'x'
// is already bound.
- if ((mode != Variable::VAR) || (var->mode() != Variable::VAR)) {
+ if ((mode != VAR) || (var->mode() != VAR)) {
// We only have vars, consts and lets in declarations.
- ASSERT(var->mode() == Variable::VAR ||
- var->mode() == Variable::CONST ||
- var->mode() == Variable::LET);
- if (harmony_block_scoping_) {
+ ASSERT(var->mode() == VAR ||
+ var->mode() == CONST ||
+ var->mode() == LET);
+ if (harmony_scoping_) {
// In harmony mode we treat re-declarations as early errors. See
// ES5 16 for a definition of early errors.
SmartArrayPointer<char> c_string = name->ToCString(DISALLOW_NULLS);
@@ -1376,8 +1400,8 @@ VariableProxy* Parser::Declare(Handle<String> name,
*ok = false;
return NULL;
}
- const char* type = (var->mode() == Variable::VAR) ? "var" :
- (var->mode() == Variable::CONST) ? "const" : "let";
+ const char* type = (var->mode() == VAR) ? "var" :
+ (var->mode() == CONST) ? "const" : "let";
Handle<String> type_string =
isolate()->factory()->NewStringFromUtf8(CStrVector(type), TENURED);
Expression* expression =
@@ -1410,14 +1434,10 @@ VariableProxy* Parser::Declare(Handle<String> name,
new(zone()) Declaration(proxy, mode, fun, top_scope_));
// For global const variables we bind the proxy to a variable.
- if (mode == Variable::CONST && declaration_scope->is_global_scope()) {
+ if (mode == CONST && declaration_scope->is_global_scope()) {
ASSERT(resolve); // should be set by all callers
Variable::Kind kind = Variable::NORMAL;
- var = new(zone()) Variable(declaration_scope,
- name,
- Variable::CONST,
- true,
- kind);
+ var = new(zone()) Variable(declaration_scope, name, CONST, true, kind);
}
// If requested and we have a local variable, bind the proxy to the variable
@@ -1500,7 +1520,7 @@ Statement* Parser::ParseNativeDeclaration(bool* ok) {
// other functions are setup when entering the surrounding scope.
SharedFunctionInfoLiteral* lit =
new(zone()) SharedFunctionInfoLiteral(isolate(), shared);
- VariableProxy* var = Declare(name, Variable::VAR, NULL, true, CHECK_OK);
+ VariableProxy* var = Declare(name, VAR, NULL, true, CHECK_OK);
return new(zone()) ExpressionStatement(new(zone()) Assignment(
isolate(), Token::INIT_VAR, var, lit, RelocInfo::kNoPosition));
}
@@ -1522,14 +1542,14 @@ Statement* Parser::ParseFunctionDeclaration(bool* ok) {
// Even if we're not at the top-level of the global or a function
// scope, we treat is as such and introduce the function with it's
// initial value upon entering the corresponding scope.
- Variable::Mode mode = harmony_block_scoping_ ? Variable::LET : Variable::VAR;
+ VariableMode mode = harmony_scoping_ ? LET : VAR;
Declare(name, mode, fun, true, CHECK_OK);
return EmptyStatement();
}
Block* Parser::ParseBlock(ZoneStringList* labels, bool* ok) {
- if (harmony_block_scoping_) return ParseScopedBlock(labels, ok);
+ if (harmony_scoping_) return ParseScopedBlock(labels, ok);
// Block ::
// '{' Statement* '}'
@@ -1555,6 +1575,11 @@ Block* Parser::ParseBlock(ZoneStringList* labels, bool* ok) {
Block* Parser::ParseScopedBlock(ZoneStringList* labels, bool* ok) {
+ // The harmony mode uses source elements instead of statements.
+ //
+ // Block ::
+ // '{' SourceElement* '}'
+
// Construct block expecting 16 statements.
Block* body = new(zone()) Block(isolate(), labels, 16, false);
Scope* saved_scope = top_scope_;
@@ -1622,7 +1647,7 @@ Block* Parser::ParseVariableDeclarations(VariableDeclarationContext var_context,
// VariableDeclarations ::
// ('var' | 'const') (Identifier ('=' AssignmentExpression)?)+[',']
- Variable::Mode mode = Variable::VAR;
+ VariableMode mode = VAR;
// True if the binding needs initialization. 'let' and 'const' declared
// bindings are created uninitialized by their declaration nodes and
// need initialization. 'var' declared bindings are always initialized
@@ -1639,7 +1664,7 @@ Block* Parser::ParseVariableDeclarations(VariableDeclarationContext var_context,
*ok = false;
return NULL;
}
- mode = Variable::CONST;
+ mode = CONST;
is_const = true;
needs_init = true;
init_op = Token::INIT_CONST;
@@ -1652,14 +1677,14 @@ Block* Parser::ParseVariableDeclarations(VariableDeclarationContext var_context,
*ok = false;
return NULL;
}
- mode = Variable::LET;
+ mode = LET;
needs_init = true;
init_op = Token::INIT_LET;
} else {
UNREACHABLE(); // by current callers
}
- Scope* declaration_scope = mode == Variable::LET
+ Scope* declaration_scope = (mode == LET)
? top_scope_ : top_scope_->DeclarationScope();
// The scope of a var/const declared variable anywhere inside a function
// is the entire function (ECMA-262, 3rd, 10.1.3, and 12.2). Thus we can
@@ -1753,6 +1778,8 @@ Block* Parser::ParseVariableDeclarations(VariableDeclarationContext var_context,
value->AsCall() == NULL &&
value->AsCallNew() == NULL) {
fni_->Infer();
+ } else {
+ fni_->RemoveLastFunction();
}
}
@@ -1848,7 +1875,7 @@ Block* Parser::ParseVariableDeclarations(VariableDeclarationContext var_context,
// as the declaration. Thus dynamic lookups are unnecessary even if the
// block scope is inside a with.
if (value != NULL) {
- bool in_with = mode == Variable::VAR ? inside_with() : false;
+ bool in_with = (mode == VAR) ? inside_with() : false;
VariableProxy* proxy =
initialization_scope->NewUnresolved(name, in_with);
Assignment* assignment =
@@ -2222,8 +2249,7 @@ TryStatement* Parser::ParseTryStatement(bool* ok) {
if (top_scope_->is_strict_mode()) {
catch_scope->EnableStrictMode();
}
- Variable::Mode mode = harmony_block_scoping_
- ? Variable::LET : Variable::VAR;
+ VariableMode mode = harmony_scoping_ ? LET : VAR;
catch_variable = catch_scope->DeclareLocal(name, mode);
Scope* saved_scope = top_scope_;
@@ -2503,6 +2529,8 @@ Expression* Parser::ParseAssignmentExpression(bool accept_IN, bool* ok) {
|| op == Token::ASSIGN)
&& (right->AsCall() == NULL && right->AsCallNew() == NULL)) {
fni_->Infer();
+ } else {
+ fni_->RemoveLastFunction();
}
fni_->Leave();
}
@@ -2614,7 +2642,7 @@ Expression* Parser::ParseBinaryExpression(int prec, bool accept_IN, bool* ok) {
case Token::NE_STRICT: cmp = Token::EQ_STRICT; break;
default: break;
}
- x = NewCompareNode(cmp, x, y, position);
+ x = new(zone()) CompareOperation(isolate(), cmp, x, y, position);
if (cmp != op) {
// The comparison was negated - add a NOT.
x = new(zone()) UnaryOperation(isolate(), Token::NOT, x, position);
@@ -2630,27 +2658,6 @@ Expression* Parser::ParseBinaryExpression(int prec, bool accept_IN, bool* ok) {
}
-Expression* Parser::NewCompareNode(Token::Value op,
- Expression* x,
- Expression* y,
- int position) {
- ASSERT(op != Token::NE && op != Token::NE_STRICT);
- if (op == Token::EQ || op == Token::EQ_STRICT) {
- bool is_strict = (op == Token::EQ_STRICT);
- Literal* x_literal = x->AsLiteral();
- if (x_literal != NULL && x_literal->IsNull()) {
- return new(zone()) CompareToNull(isolate(), is_strict, y);
- }
-
- Literal* y_literal = y->AsLiteral();
- if (y_literal != NULL && y_literal->IsNull()) {
- return new(zone()) CompareToNull(isolate(), is_strict, x);
- }
- }
- return new(zone()) CompareOperation(isolate(), op, x, y, position);
-}
-
-
Expression* Parser::ParseUnaryExpression(bool* ok) {
// UnaryExpression ::
// PostfixExpression
@@ -3707,8 +3714,7 @@ FunctionLiteral* Parser::ParseFunctionLiteral(Handle<String> function_name,
// Function declarations are function scoped in normal mode, so they are
// hoisted. In harmony block scoping mode they are block scoped, so they
// are not hoisted.
- Scope* scope = (type == FunctionLiteral::DECLARATION &&
- !harmony_block_scoping_)
+ Scope* scope = (type == FunctionLiteral::DECLARATION && !harmony_scoping_)
? NewScope(top_scope_->DeclarationScope(), Scope::FUNCTION_SCOPE, false)
: NewScope(top_scope_, Scope::FUNCTION_SCOPE, inside_with());
ZoneList<Statement*>* body = new(zone()) ZoneList<Statement*>(8);
@@ -3750,10 +3756,7 @@ FunctionLiteral* Parser::ParseFunctionLiteral(Handle<String> function_name,
reserved_loc = scanner().location();
}
- top_scope_->DeclareParameter(param_name,
- harmony_block_scoping_
- ? Variable::LET
- : Variable::VAR);
+ top_scope_->DeclareParameter(param_name, harmony_scoping_ ? LET : VAR);
num_parameters++;
if (num_parameters > kMaxNumFunctionParameters) {
ReportMessageAt(scanner().location(), "too_many_parameters",
@@ -3880,7 +3883,7 @@ FunctionLiteral* Parser::ParseFunctionLiteral(Handle<String> function_name,
}
}
- if (harmony_block_scoping_) {
+ if (harmony_scoping_) {
CheckConflictingVarDeclarations(scope, CHECK_OK);
}
@@ -5118,10 +5121,10 @@ int ScriptDataImpl::ReadNumber(byte** source) {
static ScriptDataImpl* DoPreParse(UC16CharacterStream* source,
bool allow_lazy,
ParserRecorder* recorder,
- bool harmony_block_scoping) {
+ bool harmony_scoping) {
Isolate* isolate = Isolate::Current();
JavaScriptScanner scanner(isolate->unicode_cache());
- scanner.SetHarmonyBlockScoping(harmony_block_scoping);
+ scanner.SetHarmonyScoping(harmony_scoping);
scanner.Initialize(source);
intptr_t stack_limit = isolate->stack_guard()->real_climit();
if (!preparser::PreParser::PreParseProgram(&scanner,
@@ -5143,7 +5146,7 @@ static ScriptDataImpl* DoPreParse(UC16CharacterStream* source,
// even if the preparser data is only used once.
ScriptDataImpl* ParserApi::PartialPreParse(UC16CharacterStream* source,
v8::Extension* extension,
- bool harmony_block_scoping) {
+ bool harmony_scoping) {
bool allow_lazy = FLAG_lazy && (extension == NULL);
if (!allow_lazy) {
// Partial preparsing is only about lazily compiled functions.
@@ -5151,17 +5154,17 @@ ScriptDataImpl* ParserApi::PartialPreParse(UC16CharacterStream* source,
return NULL;
}
PartialParserRecorder recorder;
- return DoPreParse(source, allow_lazy, &recorder, harmony_block_scoping);
+ return DoPreParse(source, allow_lazy, &recorder, harmony_scoping);
}
ScriptDataImpl* ParserApi::PreParse(UC16CharacterStream* source,
v8::Extension* extension,
- bool harmony_block_scoping) {
+ bool harmony_scoping) {
Handle<Script> no_script;
bool allow_lazy = FLAG_lazy && (extension == NULL);
CompleteParserRecorder recorder;
- return DoPreParse(source, allow_lazy, &recorder, harmony_block_scoping);
+ return DoPreParse(source, allow_lazy, &recorder, harmony_scoping);
}
@@ -5191,11 +5194,10 @@ bool ParserApi::Parse(CompilationInfo* info) {
ASSERT(info->function() == NULL);
FunctionLiteral* result = NULL;
Handle<Script> script = info->script();
- bool harmony_block_scoping = !info->is_native() &&
- FLAG_harmony_block_scoping;
+ bool harmony_scoping = !info->is_native() && FLAG_harmony_scoping;
if (info->is_lazy()) {
Parser parser(script, true, NULL, NULL);
- parser.SetHarmonyBlockScoping(harmony_block_scoping);
+ parser.SetHarmonyScoping(harmony_scoping);
result = parser.ParseLazy(info);
} else {
// Whether we allow %identifier(..) syntax.
@@ -5206,7 +5208,7 @@ bool ParserApi::Parse(CompilationInfo* info) {
allow_natives_syntax,
info->extension(),
pre_data);
- parser.SetHarmonyBlockScoping(harmony_block_scoping);
+ parser.SetHarmonyScoping(harmony_scoping);
if (pre_data != NULL && pre_data->has_error()) {
Scanner::Location loc = pre_data->MessageLocation();
const char* message = pre_data->BuildMessage();