Merge V8 at 3.9.24.13
Bug: 5688872
Change-Id: Id0aa8d23375030494d3189c31774059c0f5398fc
diff --git a/src/compiler.cc b/src/compiler.cc
index 5e1c4a9..2272337 100644
--- a/src/compiler.cc
+++ b/src/compiler.cc
@@ -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:
@@ -36,6 +36,7 @@
#include "full-codegen.h"
#include "gdb-jit.h"
#include "hydrogen.h"
+#include "isolate-inl.h"
#include "lithium.h"
#include "liveedit.h"
#include "parser.h"
@@ -52,28 +53,29 @@
CompilationInfo::CompilationInfo(Handle<Script> script)
: isolate_(script->GetIsolate()),
- flags_(0),
+ flags_(LanguageModeField::encode(CLASSIC_MODE)),
function_(NULL),
scope_(NULL),
+ global_scope_(NULL),
script_(script),
extension_(NULL),
pre_parse_data_(NULL),
- supports_deoptimization_(false),
osr_ast_id_(AstNode::kNoNumber) {
- Initialize(NONOPT);
+ Initialize(BASE);
}
CompilationInfo::CompilationInfo(Handle<SharedFunctionInfo> shared_info)
: isolate_(shared_info->GetIsolate()),
- flags_(IsLazy::encode(true)),
+ flags_(LanguageModeField::encode(CLASSIC_MODE) |
+ IsLazy::encode(true)),
function_(NULL),
scope_(NULL),
+ global_scope_(NULL),
shared_info_(shared_info),
script_(Handle<Script>(Script::cast(shared_info->script()))),
extension_(NULL),
pre_parse_data_(NULL),
- supports_deoptimization_(false),
osr_ast_id_(AstNode::kNoNumber) {
Initialize(BASE);
}
@@ -81,15 +83,16 @@
CompilationInfo::CompilationInfo(Handle<JSFunction> closure)
: isolate_(closure->GetIsolate()),
- flags_(IsLazy::encode(true)),
+ flags_(LanguageModeField::encode(CLASSIC_MODE) |
+ IsLazy::encode(true)),
function_(NULL),
scope_(NULL),
+ global_scope_(NULL),
closure_(closure),
shared_info_(Handle<SharedFunctionInfo>(closure->shared())),
script_(Handle<Script>(Script::cast(shared_info_->script()))),
extension_(NULL),
pre_parse_data_(NULL),
- supports_deoptimization_(false),
osr_ast_id_(AstNode::kNoNumber) {
Initialize(BASE);
}
@@ -107,6 +110,19 @@
}
+// Primitive functions are unlikely to be picked up by the stack-walking
+// profiler, so they trigger their own optimization when they're called
+// for the SharedFunctionInfo::kCallsUntilPrimitiveOptimization-th time.
+bool CompilationInfo::ShouldSelfOptimize() {
+ return FLAG_self_optimization &&
+ FLAG_crankshaft &&
+ !function()->flags()->Contains(kDontSelfOptimize) &&
+ !function()->flags()->Contains(kDontOptimize) &&
+ function()->scope()->allows_lazy_recompilation() &&
+ (shared_info().is_null() || !shared_info()->optimization_disabled());
+}
+
+
void CompilationInfo::AbortOptimization() {
Handle<Code> code(shared_info()->code());
SetCode(code);
@@ -167,7 +183,9 @@
static bool MakeCrankshaftCode(CompilationInfo* info) {
// Test if we can optimize this function when asked to. We can only
// do this after the scopes are computed.
- if (!info->AllowOptimize()) info->DisableOptimization();
+ if (!V8::UseCrankshaft()) {
+ info->DisableOptimization();
+ }
// In case we are not optimizing simply return the code from
// the full code generator.
@@ -187,7 +205,7 @@
// Fall back to using the full code generator if it's not possible
// to use the Hydrogen-based optimizing compiler. We already have
// generated code for this from the shared function object.
- if (AlwaysFullCompiler() || !FLAG_use_hydrogen) {
+ if (AlwaysFullCompiler()) {
info->SetCode(code);
return true;
}
@@ -198,8 +216,7 @@
FLAG_deopt_every_n_times == 0 ? Compiler::kDefaultMaxOptCount : 1000;
if (info->shared_info()->opt_count() > kMaxOptCount) {
info->AbortOptimization();
- Handle<JSFunction> closure = info->closure();
- info->shared_info()->DisableOptimization(*closure);
+ info->shared_info()->DisableOptimization();
// True indicates the compilation pipeline is still going, not
// necessarily that we optimized the code.
return true;
@@ -219,20 +236,22 @@
(info->osr_ast_id() != AstNode::kNoNumber &&
scope->num_parameters() + 1 + scope->num_stack_slots() > locals_limit)) {
info->AbortOptimization();
- Handle<JSFunction> closure = info->closure();
- info->shared_info()->DisableOptimization(*closure);
+ info->shared_info()->DisableOptimization();
// True indicates the compilation pipeline is still going, not
// necessarily that we optimized the code.
return true;
}
// Take --hydrogen-filter into account.
- Vector<const char> filter = CStrVector(FLAG_hydrogen_filter);
Handle<String> name = info->function()->debug_name();
- bool match = filter.is_empty() || name->IsEqualTo(filter);
- if (!match) {
- info->SetCode(code);
- return true;
+ if (*FLAG_hydrogen_filter != '\0') {
+ Vector<const char> filter = CStrVector(FLAG_hydrogen_filter);
+ if ((filter[0] == '-'
+ && name->IsEqualTo(filter.SubVector(1, filter.length())))
+ || (filter[0] != '-' && !name->IsEqualTo(filter))) {
+ info->SetCode(code);
+ return true;
+ }
}
// Recompile the unoptimized version of the code if the current version
@@ -275,7 +294,7 @@
}
Handle<Context> global_context(info->closure()->context()->global_context());
- TypeFeedbackOracle oracle(code, global_context);
+ TypeFeedbackOracle oracle(code, global_context, info->isolate());
HGraphBuilder builder(info, &oracle);
HPhase phase(HPhase::kTotal);
HGraph* graph = builder.CreateGraph();
@@ -284,7 +303,7 @@
return false;
}
- if (graph != NULL && FLAG_build_lithium) {
+ if (graph != NULL) {
Handle<Code> optimized_code = graph->Compile(info);
if (!optimized_code.is_null()) {
info->SetCode(optimized_code);
@@ -298,8 +317,7 @@
if (!builder.inline_bailout()) {
// Mark the shared code as unoptimizable unless it was an inlined
// function that bailed out.
- Handle<JSFunction> closure = info->closure();
- info->shared_info()->DisableOptimization(*closure);
+ info->shared_info()->DisableOptimization();
}
// True indicates the compilation pipeline is still going, not necessarily
// that we optimized the code.
@@ -308,9 +326,9 @@
static bool GenerateCode(CompilationInfo* info) {
- return V8::UseCrankshaft() ?
- MakeCrankshaftCode(info) :
- FullCodeGenerator::MakeCode(info);
+ return info->IsCompilingForDebugging() || !V8::UseCrankshaft() ?
+ FullCodeGenerator::MakeCode(info) :
+ MakeCrankshaftCode(info);
}
@@ -328,8 +346,7 @@
// the compilation info is set if compilation succeeded.
bool succeeded = MakeCode(info);
if (!info->shared_info().is_null()) {
- Handle<SerializedScopeInfo> scope_info =
- SerializedScopeInfo::Create(info->scope());
+ Handle<ScopeInfo> scope_info = ScopeInfo::Create(info->scope());
info->shared_info()->set_scope_info(*scope_info);
}
return succeeded;
@@ -371,8 +388,14 @@
// Only allow non-global compiles for eval.
ASSERT(info->is_eval() || info->is_global());
-
- if (!ParserApi::Parse(info)) return Handle<SharedFunctionInfo>::null();
+ ParsingFlags flags = kNoParsingFlags;
+ if (info->pre_parse_data() != NULL ||
+ String::cast(script->source())->length() > FLAG_min_preparse_length) {
+ flags = kAllowLazy;
+ }
+ if (!ParserApi::Parse(info, flags)) {
+ return Handle<SharedFunctionInfo>::null();
+ }
// Measure how long it takes to do the compilation; only take the
// rest of the function into account to avoid overlap with the
@@ -386,7 +409,7 @@
FunctionLiteral* lit = info->function();
LiveEditFunctionTracker live_edit_tracker(isolate, lit);
if (!MakeCode(info)) {
- isolate->StackOverflow();
+ if (!isolate->has_pending_exception()) isolate->StackOverflow();
return Handle<SharedFunctionInfo>::null();
}
@@ -397,7 +420,7 @@
lit->name(),
lit->materialized_literal_count(),
info->code(),
- SerializedScopeInfo::Create(info->scope()));
+ ScopeInfo::Create(info->scope()));
ASSERT_EQ(RelocInfo::kNoPosition, lit->function_token_position());
Compiler::SetFunctionInfo(result, lit, true, script);
@@ -430,6 +453,9 @@
// the instances of the function.
SetExpectedNofPropertiesFromEstimate(result, lit->expected_property_count());
+ script->set_compilation_state(
+ Smi::FromInt(Script::COMPILATION_STATE_COMPILED));
+
#ifdef ENABLE_DEBUGGER_SUPPORT
// Notify debugger
isolate->debugger()->OnAfterCompile(
@@ -447,7 +473,7 @@
int line_offset,
int column_offset,
v8::Extension* extension,
- ScriptDataImpl* input_pre_data,
+ ScriptDataImpl* pre_data,
Handle<Object> script_data,
NativesFlag natives) {
Isolate* isolate = source->GetIsolate();
@@ -478,24 +504,6 @@
// for small sources, odds are that there aren't many functions
// that would be compiled lazily anyway, so we skip the preparse step
// in that case too.
- ScriptDataImpl* pre_data = input_pre_data;
- bool harmony_block_scoping = natives != NATIVES_CODE &&
- FLAG_harmony_block_scoping;
- if (pre_data == NULL
- && source_length >= FLAG_min_preparse_length) {
- if (source->IsExternalTwoByteString()) {
- ExternalTwoByteStringUC16CharacterStream stream(
- Handle<ExternalTwoByteString>::cast(source), 0, source->length());
- pre_data = ParserApi::PartialPreParse(&stream,
- extension,
- harmony_block_scoping);
- } else {
- GenericStringUC16CharacterStream stream(source, 0, source->length());
- pre_data = ParserApi::PartialPreParse(&stream,
- extension,
- harmony_block_scoping);
- }
- }
// Create a script object describing the script to be compiled.
Handle<Script> script = FACTORY->NewScript(source);
@@ -516,15 +524,13 @@
info.MarkAsGlobal();
info.SetExtension(extension);
info.SetPreParseData(pre_data);
+ if (FLAG_use_strict) {
+ info.SetLanguageMode(FLAG_harmony_scoping ? EXTENDED_MODE : STRICT_MODE);
+ }
result = MakeFunctionInfo(&info);
if (extension == NULL && !result.is_null()) {
compilation_cache->PutScript(source, result);
}
-
- // Get rid of the pre-parsing data (if necessary).
- if (input_pre_data == NULL && pre_data != NULL) {
- delete pre_data;
- }
}
if (result.is_null()) isolate->ReportPendingMessages();
@@ -535,7 +541,8 @@
Handle<SharedFunctionInfo> Compiler::CompileEval(Handle<String> source,
Handle<Context> context,
bool is_global,
- StrictModeFlag strict_mode) {
+ LanguageMode language_mode,
+ int scope_position) {
Isolate* isolate = source->GetIsolate();
int source_length = source->length();
isolate->counters()->total_eval_size()->Increment(source_length);
@@ -551,7 +558,8 @@
result = compilation_cache->LookupEval(source,
context,
is_global,
- strict_mode);
+ language_mode,
+ scope_position);
if (result.is_null()) {
// Create a script object describing the script to be compiled.
@@ -559,16 +567,24 @@
CompilationInfo info(script);
info.MarkAsEval();
if (is_global) info.MarkAsGlobal();
- if (strict_mode == kStrictMode) info.MarkAsStrictMode();
+ info.SetLanguageMode(language_mode);
info.SetCallingContext(context);
result = MakeFunctionInfo(&info);
if (!result.is_null()) {
- CompilationCache* compilation_cache = isolate->compilation_cache();
- // If caller is strict mode, the result must be strict as well,
- // but not the other way around. Consider:
+ // Explicitly disable optimization for eval code. We're not yet prepared
+ // to handle eval-code in the optimizing compiler.
+ result->DisableOptimization();
+
+ // If caller is strict mode, the result must be in strict mode or
+ // extended mode as well, but not the other way around. Consider:
// eval("'use strict'; ...");
- ASSERT(strict_mode == kNonStrictMode || result->strict_mode());
- compilation_cache->PutEval(source, context, is_global, result);
+ ASSERT(language_mode != STRICT_MODE || !result->is_classic_mode());
+ // If caller is in extended mode, the result must also be in
+ // extended mode.
+ ASSERT(language_mode != EXTENDED_MODE ||
+ result->is_extended_mode());
+ compilation_cache->PutEval(
+ source, context, is_global, result, scope_position);
}
}
@@ -591,17 +607,16 @@
isolate->counters()->total_compile_size()->Increment(compiled_size);
// Generate the AST for the lazily compiled function.
- if (ParserApi::Parse(info)) {
+ if (ParserApi::Parse(info, kNoParsingFlags)) {
// Measure how long it takes to do the lazy compilation; only take the
// rest of the function into account to avoid overlap with the lazy
// parsing statistics.
HistogramTimerScope timer(isolate->counters()->compile_lazy());
- // After parsing we know function's strict mode. Remember it.
- if (info->function()->strict_mode()) {
- shared->set_strict_mode(true);
- info->MarkAsStrictMode();
- }
+ // After parsing we know the function's language mode. Remember it.
+ LanguageMode language_mode = info->function()->language_mode();
+ info->SetLanguageMode(language_mode);
+ shared->set_language_mode(language_mode);
// Compile the code.
if (!MakeCode(info)) {
@@ -620,16 +635,15 @@
RecordFunctionCompilation(Logger::LAZY_COMPILE_TAG, info, shared);
if (info->IsOptimizing()) {
- ASSERT(shared->scope_info() != SerializedScopeInfo::Empty());
+ ASSERT(shared->scope_info() != ScopeInfo::Empty());
function->ReplaceCode(*code);
} else {
// Update the shared function info with the compiled code and the
// scope info. Please note, that the order of the shared function
// info initialization is important since set_scope_info might
// trigger a GC, causing the ASSERT below to be invalid if the code
- // was flushed. By settting the code object last we avoid this.
- Handle<SerializedScopeInfo> scope_info =
- SerializedScopeInfo::Create(info->scope());
+ // was flushed. By setting the code object last we avoid this.
+ Handle<ScopeInfo> scope_info = ScopeInfo::Create(info->scope());
shared->set_scope_info(*scope_info);
shared->set_code(*code);
if (!function.is_null()) {
@@ -652,8 +666,13 @@
// Check the function has compiled code.
ASSERT(shared->is_compiled());
shared->set_code_age(0);
+ shared->set_dont_optimize(lit->flags()->Contains(kDontOptimize));
+ shared->set_dont_inline(lit->flags()->Contains(kDontInline));
+ shared->set_ast_node_count(lit->ast_node_count());
- if (info->AllowOptimize() && !shared->optimization_disabled()) {
+ if (V8::UseCrankshaft()&&
+ !function.is_null() &&
+ !shared->optimization_disabled()) {
// If we're asked to always optimize, we compile the optimized
// version of the function right away - unless the debugger is
// active as it makes no sense to compile optimized code then.
@@ -681,7 +700,7 @@
CompilationInfo info(script);
info.SetFunction(literal);
info.SetScope(literal->scope());
- if (literal->scope()->is_strict_mode()) info.MarkAsStrictMode();
+ info.SetLanguageMode(literal->scope()->language_mode());
LiveEditFunctionTracker live_edit_tracker(info.isolate(), literal);
// Determine if the function can be lazily compiled. This is necessary to
@@ -692,7 +711,7 @@
bool allow_lazy = literal->AllowsLazyCompilation() &&
!LiveEditFunctionTracker::IsActive(info.isolate());
- Handle<SerializedScopeInfo> scope_info(SerializedScopeInfo::Empty());
+ Handle<ScopeInfo> scope_info(ScopeInfo::Empty());
// Generate code
if (FLAG_lazy && allow_lazy) {
@@ -701,7 +720,7 @@
} else if ((V8::UseCrankshaft() && MakeCrankshaftCode(&info)) ||
(!V8::UseCrankshaft() && FullCodeGenerator::MakeCode(&info))) {
ASSERT(!info.code().is_null());
- scope_info = SerializedScopeInfo::Create(info.scope());
+ scope_info = ScopeInfo::Create(info.scope());
} else {
return Handle<SharedFunctionInfo>::null();
}
@@ -733,8 +752,8 @@
FunctionLiteral* lit,
bool is_toplevel,
Handle<Script> script) {
- function_info->set_length(lit->num_parameters());
- function_info->set_formal_parameter_count(lit->num_parameters());
+ function_info->set_length(lit->parameter_count());
+ function_info->set_formal_parameter_count(lit->parameter_count());
function_info->set_script(*script);
function_info->set_function_token_position(lit->function_token_position());
function_info->set_start_position(lit->start_position());
@@ -747,9 +766,13 @@
lit->has_only_simple_this_property_assignments(),
*lit->this_property_assignments());
function_info->set_allows_lazy_compilation(lit->AllowsLazyCompilation());
- function_info->set_strict_mode(lit->strict_mode());
+ 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_is_function(lit->is_function());
+ function_info->set_dont_optimize(lit->flags()->Contains(kDontOptimize));
+ function_info->set_dont_inline(lit->flags()->Contains(kDontInline));
}