summaryrefslogtreecommitdiff
path: root/chromium/v8/src/parser.cc
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/v8/src/parser.cc')
-rw-r--r--chromium/v8/src/parser.cc87
1 files changed, 72 insertions, 15 deletions
diff --git a/chromium/v8/src/parser.cc b/chromium/v8/src/parser.cc
index df568ef1bbb..05ae11e4291 100644
--- a/chromium/v8/src/parser.cc
+++ b/chromium/v8/src/parser.cc
@@ -542,6 +542,7 @@ Parser::Parser(CompilationInfo* info)
scanner_(isolate_->unicode_cache()),
reusable_preparser_(NULL),
top_scope_(NULL),
+ original_scope_(NULL),
current_function_state_(NULL),
target_stack_(NULL),
extension_(info->extension()),
@@ -568,10 +569,13 @@ Parser::Parser(CompilationInfo* info)
FunctionLiteral* Parser::ParseProgram() {
- HistogramTimerScope timer(isolate()->counters()->parse());
+ HistogramTimerScope timer_scope(isolate()->counters()->parse());
Handle<String> source(String::cast(script_->source()));
isolate()->counters()->total_parse_size()->Increment(source->length());
- int64_t start = FLAG_trace_parse ? OS::Ticks() : 0;
+ ElapsedTimer timer;
+ if (FLAG_trace_parse) {
+ timer.Start();
+ }
fni_ = new(zone()) FuncNameInferrer(isolate(), zone());
// Initialize parser state.
@@ -592,7 +596,7 @@ FunctionLiteral* Parser::ParseProgram() {
}
if (FLAG_trace_parse && result != NULL) {
- double ms = static_cast<double>(OS::Ticks() - start) / 1000;
+ double ms = timer.Elapsed().InMillisecondsF();
if (info()->is_eval()) {
PrintF("[parsing eval");
} else if (info()->script()->name()->IsString()) {
@@ -622,6 +626,7 @@ FunctionLiteral* Parser::DoParseProgram(CompilationInfo* info,
if (!info->context().is_null()) {
scope = Scope::DeserializeScopeChain(*info->context(), scope, zone());
}
+ original_scope_ = scope;
if (info->is_eval()) {
if (!scope->is_global_scope() || info->language_mode() != CLASSIC_MODE) {
scope = NewScope(scope, EVAL_SCOPE);
@@ -682,6 +687,8 @@ FunctionLiteral* Parser::DoParseProgram(CompilationInfo* info,
FunctionLiteral::kNotParenthesized,
FunctionLiteral::kNotGenerator);
result->set_ast_properties(factory()->visitor()->ast_properties());
+ result->set_dont_optimize_reason(
+ factory()->visitor()->dont_optimize_reason());
} else if (stack_overflow_) {
isolate()->StackOverflow();
}
@@ -695,10 +702,13 @@ FunctionLiteral* Parser::DoParseProgram(CompilationInfo* info,
FunctionLiteral* Parser::ParseLazy() {
- HistogramTimerScope timer(isolate()->counters()->parse_lazy());
+ HistogramTimerScope timer_scope(isolate()->counters()->parse_lazy());
Handle<String> source(String::cast(script_->source()));
isolate()->counters()->total_parse_size()->Increment(source->length());
- int64_t start = FLAG_trace_parse ? OS::Ticks() : 0;
+ ElapsedTimer timer;
+ if (FLAG_trace_parse) {
+ timer.Start();
+ }
Handle<SharedFunctionInfo> shared_info = info()->shared_info();
// Initialize parser state.
@@ -718,7 +728,7 @@ FunctionLiteral* Parser::ParseLazy() {
}
if (FLAG_trace_parse && result != NULL) {
- double ms = static_cast<double>(OS::Ticks() - start) / 1000;
+ double ms = timer.Elapsed().InMillisecondsF();
SmartArrayPointer<char> name_chars = result->debug_name()->ToCString();
PrintF("[parsing function: %s - took %0.3f ms]\n", *name_chars, ms);
}
@@ -749,6 +759,7 @@ FunctionLiteral* Parser::ParseLazy(Utf16CharacterStream* source) {
scope = Scope::DeserializeScopeChain(info()->closure()->context(), scope,
zone());
}
+ original_scope_ = scope;
FunctionState function_state(this, scope, isolate());
ASSERT(scope->language_mode() != STRICT_MODE || !info()->is_classic_mode());
ASSERT(scope->language_mode() != EXTENDED_MODE ||
@@ -3197,6 +3208,20 @@ Expression* Parser::ParseUnaryExpression(bool* ok) {
factory()->NewNumberLiteral(1),
position);
}
+ // The same idea for '-foo' => 'foo*(-1)'.
+ if (op == Token::SUB) {
+ return factory()->NewBinaryOperation(Token::MUL,
+ expression,
+ factory()->NewNumberLiteral(-1),
+ position);
+ }
+ // ...and one more time for '~foo' => 'foo^(~0)'.
+ if (op == Token::BIT_NOT) {
+ return factory()->NewBinaryOperation(Token::BIT_XOR,
+ expression,
+ factory()->NewNumberLiteral(~0),
+ position);
+ }
return factory()->NewUnaryOperation(op, expression, position);
@@ -3721,8 +3746,9 @@ bool CompileTimeValue::IsCompileTimeValue(Expression* expression) {
}
-Handle<FixedArray> CompileTimeValue::GetValue(Expression* expression) {
- Factory* factory = Isolate::Current()->factory();
+Handle<FixedArray> CompileTimeValue::GetValue(Isolate* isolate,
+ Expression* expression) {
+ Factory* factory = isolate->factory();
ASSERT(IsCompileTimeValue(expression));
Handle<FixedArray> result = factory->NewFixedArray(2, TENURED);
ObjectLiteral* object_literal = expression->AsObjectLiteral();
@@ -3761,7 +3787,7 @@ Handle<Object> Parser::GetBoilerplateValue(Expression* expression) {
return expression->AsLiteral()->value();
}
if (CompileTimeValue::IsCompileTimeValue(expression)) {
- return CompileTimeValue::GetValue(expression);
+ return CompileTimeValue::GetValue(isolate(), expression);
}
return isolate()->factory()->uninitialized_value();
}
@@ -4265,10 +4291,38 @@ FunctionLiteral* Parser::ParseFunctionLiteral(
// 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.
+ //
+ // One tricky case are function declarations in a local sloppy-mode eval:
+ // their declaration is hoisted, but they still see the local scope. E.g.,
+ //
+ // function() {
+ // var x = 0
+ // try { throw 1 } catch (x) { eval("function g() { return x }") }
+ // return g()
+ // }
+ //
+ // needs to return 1. To distinguish such cases, we need to detect
+ // (1) whether a function stems from a sloppy eval, and
+ // (2) whether it actually hoists across the eval.
+ // Unfortunately, we do not represent sloppy eval scopes, so we do not have
+ // either information available directly, especially not when lazily compiling
+ // a function like 'g'. We hence rely on the following invariants:
+ // - (1) is the case iff the innermost scope of the deserialized scope chain
+ // under which we compile is _not_ a declaration scope. This holds because
+ // in all normal cases, function declarations are fully hoisted to a
+ // declaration scope and compiled relative to that.
+ // - (2) is the case iff the current declaration scope is still the original
+ // one relative to the deserialized scope chain. Otherwise we must be
+ // compiling a function in an inner declaration scope in the eval, e.g. a
+ // nested function, and hoisting works normally relative to that.
+ Scope* declaration_scope = top_scope_->DeclarationScope();
+ Scope* original_declaration_scope = original_scope_->DeclarationScope();
Scope* scope =
- (function_type == FunctionLiteral::DECLARATION && !is_extended_mode())
- ? NewScope(top_scope_->DeclarationScope(), FUNCTION_SCOPE)
- : NewScope(top_scope_, FUNCTION_SCOPE);
+ function_type == FunctionLiteral::DECLARATION && !is_extended_mode() &&
+ (original_scope_ == original_declaration_scope ||
+ declaration_scope != original_declaration_scope)
+ ? NewScope(declaration_scope, FUNCTION_SCOPE)
+ : NewScope(top_scope_, FUNCTION_SCOPE);
ZoneList<Statement*>* body = NULL;
int materialized_literal_count = -1;
int expected_property_count = -1;
@@ -4282,6 +4336,7 @@ FunctionLiteral* Parser::ParseFunctionLiteral(
? FunctionLiteral::kIsGenerator
: FunctionLiteral::kNotGenerator;
AstProperties ast_properties;
+ BailoutReason dont_optimize_reason = kNoReason;
// Parse function body.
{ FunctionState function_state(this, scope, isolate());
top_scope_->SetScopeName(function_name);
@@ -4541,6 +4596,7 @@ FunctionLiteral* Parser::ParseFunctionLiteral(
CHECK_OK);
}
ast_properties = *factory()->visitor()->ast_properties();
+ dont_optimize_reason = factory()->visitor()->dont_optimize_reason();
}
if (is_extended_mode()) {
@@ -4562,6 +4618,7 @@ FunctionLiteral* Parser::ParseFunctionLiteral(
generator);
function_literal->set_function_token_position(function_token_position);
function_literal->set_ast_properties(&ast_properties);
+ function_literal->set_dont_optimize_reason(dont_optimize_reason);
if (fni_ != NULL && should_infer_name) fni_->AddFunction(function_literal);
return function_literal;
@@ -4972,7 +5029,7 @@ RegExpParser::RegExpParser(FlatStringReader* in,
Handle<String>* error,
bool multiline,
Zone* zone)
- : isolate_(Isolate::Current()),
+ : isolate_(zone->isolate()),
zone_(zone),
error_(error),
captures_(NULL),
@@ -5844,9 +5901,9 @@ int ScriptDataImpl::ReadNumber(byte** source) {
// Create a Scanner for the preparser to use as input, and preparse the source.
-ScriptDataImpl* PreParserApi::PreParse(Utf16CharacterStream* source) {
+ScriptDataImpl* PreParserApi::PreParse(Isolate* isolate,
+ Utf16CharacterStream* source) {
CompleteParserRecorder recorder;
- Isolate* isolate = Isolate::Current();
HistogramTimerScope timer(isolate->counters()->pre_parse());
Scanner scanner(isolate->unicode_cache());
intptr_t stack_limit = isolate->stack_guard()->real_climit();