#include "src/messages.h"
#include "src/parser.h"
#include "src/preparser.h"
-#include "src/runtime.h"
+#include "src/runtime/runtime.h"
#include "src/scanner-character-streams.h"
#include "src/scopeinfo.h"
#include "src/string-stream.h"
// ----------------------------------------------------------------------------
// Implementation of Parser
-class ParserTraits::Checkpoint
- : public ParserBase<ParserTraits>::CheckpointBase {
- public:
- explicit Checkpoint(ParserBase<ParserTraits>* parser)
- : CheckpointBase(parser), parser_(parser) {
- saved_ast_node_id_gen_ = *parser_->ast_node_id_gen_;
- }
-
- void Restore() {
- CheckpointBase::Restore();
- *parser_->ast_node_id_gen_ = saved_ast_node_id_gen_;
- }
-
- private:
- ParserBase<ParserTraits>* parser_;
- AstNode::IdGen saved_ast_node_id_gen_;
-};
-
-
bool ParserTraits::IsEvalOrArguments(const AstRawString* identifier) const {
return identifier == parser_->ast_value_factory()->eval_string() ||
identifier == parser_->ast_value_factory()->arguments_string();
}
-bool ParserTraits::BuildSIMD128LoadStoreExpression(
- Expression** expression, ZoneList<Expression*>* arguments, int pos,
- AstNodeFactory<AstConstructionVisitor>* factory) {
- Property* prop = (*expression)->AsProperty();
- Expression* tarray_op_literal = NULL;
-
- if (prop) {
- Property* simd_type_prop = prop->obj()->AsProperty();
- if (simd_type_prop) {
- VariableProxy* simd_var = simd_type_prop->obj()->AsVariableProxy();
- if (simd_var && simd_var->raw_name() &&
- simd_var->raw_name()->IsOneByteEqualTo("SIMD")) {
- Literal* type_literal = simd_type_prop->key()->AsLiteral();
- if (type_literal && type_literal->raw_value() &&
- type_literal->raw_value()->AsString()) {
- const AstRawString* type_literal_raw_string =
- type_literal->raw_value()->AsString();
- if (type_literal_raw_string->IsOneByteEqualTo("float32x4")) {
- Literal* op_literal = prop->key()->AsLiteral();
- if (op_literal && op_literal->raw_value() &&
- op_literal->raw_value()->AsString()) {
- const AstRawString* op_raw_string =
- op_literal->raw_value()->AsString();
- AstValueFactory* ast_factory = parser_->ast_value_factory();
- if (op_raw_string->IsOneByteEqualTo("load")) {
- const AstRawString* op_str =
- ast_factory->GetOneByteString("_getFloat32x4XYZW");
- tarray_op_literal =
- factory->NewStringLiteral(op_str, RelocInfo::kNoPosition);
- } else if (op_raw_string->IsOneByteEqualTo("loadX")) {
- const AstRawString* op_str =
- ast_factory->GetOneByteString("_getFloat32x4X");
- tarray_op_literal =
- factory->NewStringLiteral(op_str, RelocInfo::kNoPosition);
- } else if (op_raw_string->IsOneByteEqualTo("loadXY")) {
- const AstRawString* op_str =
- ast_factory->GetOneByteString("_getFloat32x4XY");
- tarray_op_literal =
- factory->NewStringLiteral(op_str, RelocInfo::kNoPosition);
- } else if (op_raw_string->IsOneByteEqualTo("loadXYZ")) {
- const AstRawString* op_str =
- ast_factory->GetOneByteString("_getFloat32x4XYZ");
- tarray_op_literal =
- factory->NewStringLiteral(op_str, RelocInfo::kNoPosition);
- } else if (op_raw_string->IsOneByteEqualTo("store")) {
- const AstRawString* op_str =
- ast_factory->GetOneByteString("_setFloat32x4XYZW");
- tarray_op_literal =
- factory->NewStringLiteral(op_str, RelocInfo::kNoPosition);
- } else if (op_raw_string->IsOneByteEqualTo("storeX")) {
- const AstRawString* op_str =
- ast_factory->GetOneByteString("_setFloat32x4X");
- tarray_op_literal =
- factory->NewStringLiteral(op_str, RelocInfo::kNoPosition);
- } else if (op_raw_string->IsOneByteEqualTo("storeXY")) {
- const AstRawString* op_str =
- ast_factory->GetOneByteString("_setFloat32x4XY");
- tarray_op_literal =
- factory->NewStringLiteral(op_str, RelocInfo::kNoPosition);
- } else if (op_raw_string->IsOneByteEqualTo("storeXYZ")) {
- const AstRawString* op_str =
- ast_factory->GetOneByteString("_setFloat32x4XYZ");
- tarray_op_literal =
- factory->NewStringLiteral(op_str, RelocInfo::kNoPosition);
- }
- }
- } else if (type_literal_raw_string->IsOneByteEqualTo("int32x4")) {
- Literal* op_literal = prop->key()->AsLiteral();
- if (op_literal && op_literal->raw_value() &&
- op_literal->raw_value()->AsString()) {
- const AstRawString* op_raw_string =
- op_literal->raw_value()->AsString();
- AstValueFactory* ast_factory = parser_->ast_value_factory();
- if (op_raw_string->IsOneByteEqualTo("load")) {
- const AstRawString* op_str =
- ast_factory->GetOneByteString("_getInt32x4XYZW");
- tarray_op_literal =
- factory->NewStringLiteral(op_str, RelocInfo::kNoPosition);
- } else if (op_raw_string->IsOneByteEqualTo("loadX")) {
- const AstRawString* op_str =
- ast_factory->GetOneByteString("_getInt32x4X");
- tarray_op_literal =
- factory->NewStringLiteral(op_str, RelocInfo::kNoPosition);
- } else if (op_raw_string->IsOneByteEqualTo("loadXY")) {
- const AstRawString* op_str =
- ast_factory->GetOneByteString("_getInt32x4XY");
- tarray_op_literal =
- factory->NewStringLiteral(op_str, RelocInfo::kNoPosition);
- } else if (op_raw_string->IsOneByteEqualTo("loadXYZ")) {
- const AstRawString* op_str =
- ast_factory->GetOneByteString("_getInt32x4XYZ");
- tarray_op_literal =
- factory->NewStringLiteral(op_str, RelocInfo::kNoPosition);
- } else if (op_raw_string->IsOneByteEqualTo("store")) {
- const AstRawString* op_str =
- ast_factory->GetOneByteString("_setInt32x4XYZW");
- tarray_op_literal =
- factory->NewStringLiteral(op_str, RelocInfo::kNoPosition);
- } else if (op_raw_string->IsOneByteEqualTo("storeX")) {
- const AstRawString* op_str =
- ast_factory->GetOneByteString("_setInt32x4X");
- tarray_op_literal =
- factory->NewStringLiteral(op_str, RelocInfo::kNoPosition);
- } else if (op_raw_string->IsOneByteEqualTo("storeXY")) {
- const AstRawString* op_str =
- ast_factory->GetOneByteString("_setInt32x4XY");
- tarray_op_literal =
- factory->NewStringLiteral(op_str, RelocInfo::kNoPosition);
- } else if (op_raw_string->IsOneByteEqualTo("storeXYZ")) {
- const AstRawString* op_str =
- ast_factory->GetOneByteString("_setInt32x4XYZ");
- tarray_op_literal =
- factory->NewStringLiteral(op_str, RelocInfo::kNoPosition);
- }
- }
- } else if (type_literal_raw_string->IsOneByteEqualTo("float64x2")) {
- Literal* op_literal = prop->key()->AsLiteral();
- if (op_literal && op_literal->raw_value() &&
- op_literal->raw_value()->AsString()) {
- const AstRawString* op_raw_string =
- op_literal->raw_value()->AsString();
- AstValueFactory* ast_factory = parser_->ast_value_factory();
- if (op_raw_string->IsOneByteEqualTo("load")) {
- const AstRawString* op_str =
- ast_factory->GetOneByteString("_getFloat64x2XY");
- tarray_op_literal =
- factory->NewStringLiteral(op_str, RelocInfo::kNoPosition);
- } else if (op_raw_string->IsOneByteEqualTo("loadX")) {
- const AstRawString* op_str =
- ast_factory->GetOneByteString("_getFloat64x2X");
- tarray_op_literal =
- factory->NewStringLiteral(op_str, RelocInfo::kNoPosition);
- } else if (op_raw_string->IsOneByteEqualTo("store")) {
- const AstRawString* op_str =
- ast_factory->GetOneByteString("_setFloat64x2XY");
- tarray_op_literal =
- factory->NewStringLiteral(op_str, RelocInfo::kNoPosition);
- } else if (op_raw_string->IsOneByteEqualTo("storeX")) {
- const AstRawString* op_str =
- ast_factory->GetOneByteString("_setFloat64x2X");
- tarray_op_literal =
- factory->NewStringLiteral(op_str, RelocInfo::kNoPosition);
- }
- }
- }
- }
- }
- }
- }
-
- if (tarray_op_literal) {
- if (arguments && arguments->length() == 2) {
- Expression* tarray = arguments->at(0);
- Expression* index = arguments->at(1);
- Expression* tarray_op =
- factory->NewProperty(tarray, tarray_op_literal, pos);
- Zone* zone = parser_->zone();
- ZoneList<Expression*>* tarray_op_args =
- new (zone) ZoneList<Expression*>(1, zone);
- tarray_op_args->Add(index, zone);
- *expression = factory->NewCall(tarray_op, tarray_op_args, pos);
- return true;
- } else if (arguments && arguments->length() == 3) {
- Expression* tarray = arguments->at(0);
- Expression* index = arguments->at(1);
- Expression* value = arguments->at(2);
- Expression* tarray_op =
- factory->NewProperty(tarray, tarray_op_literal, pos);
- Zone* zone = parser_->zone();
- ZoneList<Expression*>* tarray_op_args =
- new (zone) ZoneList<Expression*>(1, zone);
- tarray_op_args->Add(index, zone);
- tarray_op_args->Add(value, zone);
- *expression = factory->NewCall(tarray_op, tarray_op_args, pos);
- return true;
- }
- }
- return false;
-}
-
-
Expression* ParserTraits::BuildUnaryExpression(
Expression* expression, Token::Value op, int pos,
AstNodeFactory<AstConstructionVisitor>* factory) {
Expression* ParserTraits::NewThrowReferenceError(const char* message, int pos) {
return NewThrowError(
parser_->ast_value_factory()->make_reference_error_string(), message,
- NULL, pos);
+ parser_->ast_value_factory()->empty_string(), pos);
}
const AstRawString* constructor, const char* message,
const AstRawString* arg, int pos) {
Zone* zone = parser_->zone();
- int argc = arg != NULL ? 1 : 0;
const AstRawString* type =
parser_->ast_value_factory()->GetOneByteString(message);
- ZoneList<const AstRawString*>* array =
- new (zone) ZoneList<const AstRawString*>(argc, zone);
- if (arg != NULL) {
- array->Add(arg, zone);
- }
ZoneList<Expression*>* args = new (zone) ZoneList<Expression*>(2, zone);
args->Add(parser_->factory()->NewStringLiteral(type, pos), zone);
- args->Add(parser_->factory()->NewStringListLiteral(array, pos), zone);
+ args->Add(parser_->factory()->NewStringLiteral(arg, pos), zone);
CallRuntime* call_constructor =
parser_->factory()->NewCallRuntime(constructor, NULL, args, pos);
return parser_->factory()->NewThrow(call_constructor, pos);
pos);
}
-Expression* ParserTraits::ClassLiteral(
+Expression* ParserTraits::ClassExpression(
const AstRawString* name, Expression* extends, Expression* constructor,
- ZoneList<ObjectLiteral::Property*>* properties, int pos,
- AstNodeFactory<AstConstructionVisitor>* factory) {
- return factory->NewClassLiteral(name, extends, constructor, properties, pos);
+ ZoneList<ObjectLiteral::Property*>* properties, int start_position,
+ int end_position, AstNodeFactory<AstConstructionVisitor>* factory) {
+ return factory->NewClassLiteral(name, extends, constructor, properties,
+ start_position, end_position);
}
Literal* ParserTraits::ExpressionFromLiteral(
Parser::Parser(CompilationInfo* info, ParseInfo* parse_info)
: ParserBase<ParserTraits>(&scanner_, parse_info->stack_limit,
- info->extension(), NULL, info->zone(),
- info->ast_node_id_gen(), this),
+ info->extension(), NULL, info->zone(), this),
scanner_(parse_info->unicode_cache),
reusable_preparser_(NULL),
original_scope_(NULL),
// Initialize parser state.
CompleteParserRecorder recorder;
+ debug_saved_compile_options_ = compile_options();
if (compile_options() == ScriptCompiler::kProduceParserCache) {
log_ = &recorder;
} else if (compile_options() == ScriptCompiler::kConsumeParserCache) {
ParsingModeScope parsing_mode(this, mode);
// Enters 'scope'.
- FunctionState function_state(&function_state_, &scope_, *scope, zone(),
- ast_value_factory(), info->ast_node_id_gen());
+ AstNodeFactory<AstConstructionVisitor> function_factory(
+ ast_value_factory());
+ FunctionState function_state(&function_state_, &scope_, *scope,
+ &function_factory);
scope_->SetStrictMode(info->strict_mode());
ZoneList<Statement*>* body = new(zone()) ZoneList<Statement*>(16, zone());
zone());
}
original_scope_ = scope;
- FunctionState function_state(&function_state_, &scope_, scope, zone(),
- ast_value_factory(),
- info()->ast_node_id_gen());
+ AstNodeFactory<AstConstructionVisitor> function_factory(
+ ast_value_factory());
+ FunctionState function_state(&function_state_, &scope_, scope,
+ &function_factory);
DCHECK(scope->strict_mode() == SLOPPY || info()->strict_mode() == STRICT);
DCHECK(info()->strict_mode() == shared_info->strict_mode());
scope->SetStrictMode(shared_info->strict_mode());
Expression* value = ParseClassLiteral(name, scanner()->location(),
is_strict_reserved, pos, CHECK_OK);
- Block* block = factory()->NewBlock(NULL, 1, true, pos);
- VariableMode mode = LET;
- VariableProxy* proxy = NewUnresolved(name, mode, Interface::NewValue());
+ VariableProxy* proxy = NewUnresolved(name, LET, Interface::NewValue());
Declaration* declaration =
- factory()->NewVariableDeclaration(proxy, mode, scope_, pos);
+ factory()->NewVariableDeclaration(proxy, LET, scope_, pos);
Declare(declaration, true, CHECK_OK);
+ proxy->var()->set_initializer_position(pos);
Token::Value init_op = Token::INIT_LET;
Assignment* assignment = factory()->NewAssignment(init_op, proxy, value, pos);
- block->AddStatement(
- factory()->NewExpressionStatement(assignment, RelocInfo::kNoPosition),
- zone());
-
+ Statement* assignment_statement =
+ factory()->NewExpressionStatement(assignment, RelocInfo::kNoPosition);
if (names) names->Add(name, zone());
- return block;
+ return assignment_statement;
}
Block* block = factory()->NewBlock(NULL, 1, true, pos);
int nvars = 0; // the number of variables declared
const AstRawString* name = NULL;
+ bool is_for_iteration_variable;
do {
if (fni_ != NULL) fni_->Enter();
// For let/const declarations in harmony mode, we can also immediately
// pre-resolve the proxy because it resides in the same scope as the
// declaration.
+ is_for_iteration_variable =
+ var_context == kForStatement &&
+ (peek() == Token::IN || PeekContextualKeyword(CStrVector("of")));
+ if (is_for_iteration_variable && mode == CONST) {
+ needs_init = false;
+ }
+
Interface* interface =
is_const ? Interface::NewConst() : Interface::NewValue();
VariableProxy* proxy = NewUnresolved(name, mode, interface);
Expression* value = NULL;
int pos = -1;
// Harmony consts have non-optional initializers.
- if (peek() == Token::ASSIGN || mode == CONST) {
+ if (peek() == Token::ASSIGN ||
+ (mode == CONST && !is_for_iteration_variable)) {
Expect(Token::ASSIGN, CHECK_OK);
pos = position();
value = ParseAssignmentExpression(var_context != kForStatement, CHECK_OK);
}
// Record the end position of the initializer.
- if (proxy->var() != NULL) {
+ if (proxy->is_resolved()) {
proxy->var()->set_initializer_position(position());
}
// If there was a single non-const declaration, return it in the output
// parameter for possible use by for/in.
- if (nvars == 1 && !is_const) {
+ if (nvars == 1 && (!is_const || is_for_iteration_variable)) {
*out = name;
}
Expect(Token::LPAREN, CHECK_OK);
for_scope->set_start_position(scanner()->location().beg_pos);
if (peek() != Token::SEMICOLON) {
- if (peek() == Token::VAR || peek() == Token::CONST) {
+ if (peek() == Token::VAR ||
+ (peek() == Token::CONST && strict_mode() == SLOPPY)) {
bool is_const = peek() == Token::CONST;
const AstRawString* name = NULL;
VariableDeclarationProperties decl_props = kHasNoInitializers;
} else {
init = variable_statement;
}
- } else if (peek() == Token::LET && strict_mode() == STRICT) {
- DCHECK(allow_harmony_scoping());
+ } else if ((peek() == Token::LET || peek() == Token::CONST) &&
+ strict_mode() == STRICT) {
+ bool is_const = peek() == Token::CONST;
const AstRawString* name = NULL;
VariableDeclarationProperties decl_props = kHasNoInitializers;
Block* variable_statement =
if (accept_IN && CheckInOrOf(accept_OF, &mode)) {
// Rewrite a for-in statement of the form
//
- // for (let x in e) b
+ // for (let/const x in e) b
//
// into
//
// <let x' be a temporary variable>
// for (x' in e) {
- // let x;
+ // let/const x;
// x = x';
// b;
// }
scope_ = for_scope;
Expect(Token::RPAREN, CHECK_OK);
- VariableProxy* each =
- scope_->NewUnresolved(factory(), name, Interface::NewValue());
+ VariableProxy* each = scope_->NewUnresolved(factory(), name);
Statement* body = ParseStatement(NULL, CHECK_OK);
Block* body_block =
factory()->NewBlock(NULL, 3, false, RelocInfo::kNoPosition);
+ Token::Value init_op = is_const ? Token::INIT_CONST : Token::ASSIGN;
Assignment* assignment = factory()->NewAssignment(
- Token::ASSIGN, each, temp_proxy, RelocInfo::kNoPosition);
+ init_op, each, temp_proxy, RelocInfo::kNoPosition);
Statement* assignment_statement = factory()->NewExpressionStatement(
assignment, RelocInfo::kNoPosition);
body_block->AddStatement(variable_statement, zone());
Scanner::Location lhs_location = scanner()->peek_location();
Expression* expression = ParseExpression(false, CHECK_OK);
ForEachStatement::VisitMode mode;
- bool accept_OF = expression->AsVariableProxy();
+ bool accept_OF = expression->IsVariableProxy();
if (CheckInOrOf(accept_OF, &mode)) {
expression = this->CheckAndRewriteReferenceExpression(
// Too many parentheses around expression:
// (( ... )) => ...
- if (expression->parenthesization_level() > 1) return false;
+ if (expression->is_multi_parenthesized()) return false;
// Case for a single parameter:
// (foo) => ...
BailoutReason dont_optimize_reason = kNoReason;
// Parse function body.
{
- FunctionState function_state(&function_state_, &scope_, scope, zone(),
- ast_value_factory(),
- info()->ast_node_id_gen());
+ AstNodeFactory<AstConstructionVisitor> function_factory(
+ ast_value_factory());
+ FunctionState function_state(&function_state_, &scope_, scope,
+ &function_factory);
scope_->SetScopeName(function_name);
if (is_generator) {
int* materialized_literal_count,
int* expected_property_count,
bool* ok) {
+ // Temporary debugging code for tracking down a mystery crash which should
+ // never happen. The crash happens on the line where we log the function in
+ // the preparse data: log_->LogFunction(...). TODO(marja): remove this once
+ // done.
+ CHECK(materialized_literal_count);
+ CHECK(expected_property_count);
+ CHECK(debug_saved_compile_options_ == compile_options());
+ if (compile_options() == ScriptCompiler::kProduceParserCache) {
+ CHECK(log_);
+ }
+
int function_block_pos = position();
if (compile_options() == ScriptCompiler::kConsumeParserCache) {
// If we have cached data, we use it to skip parsing the function body. The
fni_ = new (zone()) FuncNameInferrer(ast_value_factory(), zone());
CompleteParserRecorder recorder;
+ debug_saved_compile_options_ = compile_options();
if (compile_options() == ScriptCompiler::kProduceParserCache) {
log_ = &recorder;
}