diff options
Diffstat (limited to 'deps/v8/src/compiler.cc')
-rw-r--r-- | deps/v8/src/compiler.cc | 194 |
1 files changed, 92 insertions, 102 deletions
diff --git a/deps/v8/src/compiler.cc b/deps/v8/src/compiler.cc index 4b539897b8..7b9f705bc3 100644 --- a/deps/v8/src/compiler.cc +++ b/deps/v8/src/compiler.cc @@ -1,29 +1,6 @@ // 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: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. #include "v8.h" @@ -141,6 +118,13 @@ void CompilationInfo::Initialize(Isolate* isolate, SetStrictMode(shared_info_->strict_mode()); } set_bailout_reason(kUnknown); + + if (!shared_info().is_null() && shared_info()->is_compiled()) { + // We should initialize the CompilationInfo feedback vector from the + // passed in shared info, rather than creating a new one. + feedback_vector_ = Handle<FixedArray>(shared_info()->feedback_vector(), + isolate); + } } @@ -249,7 +233,13 @@ bool CompilationInfo::ShouldSelfOptimize() { void CompilationInfo::PrepareForCompilation(Scope* scope) { ASSERT(scope_ == NULL); scope_ = scope; - function()->ProcessFeedbackSlots(isolate_); + + int length = function()->slot_count(); + if (feedback_vector_.is_null()) { + // Allocate the feedback vector too. + feedback_vector_ = isolate()->factory()->NewTypeFeedbackVector(length); + } + ASSERT(feedback_vector_->length() == length); } @@ -298,13 +288,9 @@ class HOptimizedGraphBuilderWithPositions: public HOptimizedGraphBuilder { // the full compiler need not be be used if a debugger is attached, but only if // break points has actually been set. static bool IsDebuggerActive(Isolate* isolate) { -#ifdef ENABLE_DEBUGGER_SUPPORT return isolate->use_crankshaft() ? isolate->debug()->has_break_points() : isolate->debugger()->IsDebuggerActive(); -#else - return false; -#endif } @@ -354,6 +340,10 @@ OptimizedCompileJob::Status OptimizedCompileJob::CreateGraph() { return AbortAndDisableOptimization(kTooManyParametersLocals); } + if (scope->HasIllegalRedeclaration()) { + return AbortAndDisableOptimization(kFunctionWithIllegalRedeclaration); + } + // Take --hydrogen-filter into account. if (!info()->closure()->PassesFilter(FLAG_hydrogen_filter)) { return AbortOptimization(kHydrogenFilter); @@ -541,7 +531,7 @@ void SetExpectedNofPropertiesFromEstimate(Handle<SharedFunctionInfo> shared, // TODO(yangguo): check whether those heuristics are still up-to-date. // We do not shrink objects that go into a snapshot (yet), so we adjust // the estimate conservatively. - if (Serializer::enabled()) { + if (Serializer::enabled(shared->GetIsolate())) { estimate += 2; } else if (FLAG_clever_optimizations) { // Inobject slack tracking will reclaim redundant inobject space later, @@ -571,6 +561,8 @@ static void UpdateSharedFunctionInfo(CompilationInfo* info) { shared->ReplaceCode(*code); if (shared->optimization_disabled()) code->set_optimizable(false); + shared->set_feedback_vector(*info->feedback_vector()); + // Set the expected number of properties for instances. FunctionLiteral* lit = info->function(); int expected = lit->expected_property_count(); @@ -633,13 +625,14 @@ static bool CompileUnoptimizedCode(CompilationInfo* info) { } -static Handle<Code> GetUnoptimizedCodeCommon(CompilationInfo* info) { +MUST_USE_RESULT static MaybeHandle<Code> GetUnoptimizedCodeCommon( + CompilationInfo* info) { VMState<COMPILER> state(info->isolate()); PostponeInterruptsScope postpone(info->isolate()); - if (!Parser::Parse(info)) return Handle<Code>::null(); + if (!Parser::Parse(info)) return MaybeHandle<Code>(); info->SetStrictMode(info->function()->strict_mode()); - if (!CompileUnoptimizedCode(info)) return Handle<Code>::null(); + if (!CompileUnoptimizedCode(info)) return MaybeHandle<Code>(); Compiler::RecordFunctionCompilation( Logger::LAZY_COMPILE_TAG, info, info->shared_info()); UpdateSharedFunctionInfo(info); @@ -648,7 +641,7 @@ static Handle<Code> GetUnoptimizedCodeCommon(CompilationInfo* info) { } -Handle<Code> Compiler::GetUnoptimizedCode(Handle<JSFunction> function) { +MaybeHandle<Code> Compiler::GetUnoptimizedCode(Handle<JSFunction> function) { ASSERT(!function->GetIsolate()->has_pending_exception()); ASSERT(!function->is_compiled()); if (function->shared()->is_compiled()) { @@ -656,39 +649,43 @@ Handle<Code> Compiler::GetUnoptimizedCode(Handle<JSFunction> function) { } CompilationInfoWithZone info(function); - Handle<Code> result = GetUnoptimizedCodeCommon(&info); - ASSERT_EQ(result.is_null(), info.isolate()->has_pending_exception()); + Handle<Code> result; + ASSIGN_RETURN_ON_EXCEPTION(info.isolate(), result, + GetUnoptimizedCodeCommon(&info), + Code); if (FLAG_always_opt && - !result.is_null() && info.isolate()->use_crankshaft() && !info.shared_info()->optimization_disabled() && !info.isolate()->DebuggerHasBreakPoints()) { - Handle<Code> opt_code = Compiler::GetOptimizedCode( - function, result, Compiler::NOT_CONCURRENT); - if (!opt_code.is_null()) result = opt_code; + Handle<Code> opt_code; + if (Compiler::GetOptimizedCode( + function, result, + Compiler::NOT_CONCURRENT).ToHandle(&opt_code)) { + result = opt_code; + } } return result; } -Handle<Code> Compiler::GetUnoptimizedCode(Handle<SharedFunctionInfo> shared) { +MaybeHandle<Code> Compiler::GetUnoptimizedCode( + Handle<SharedFunctionInfo> shared) { ASSERT(!shared->GetIsolate()->has_pending_exception()); ASSERT(!shared->is_compiled()); CompilationInfoWithZone info(shared); - Handle<Code> result = GetUnoptimizedCodeCommon(&info); - ASSERT_EQ(result.is_null(), info.isolate()->has_pending_exception()); - return result; + return GetUnoptimizedCodeCommon(&info); } bool Compiler::EnsureCompiled(Handle<JSFunction> function, ClearExceptionFlag flag) { if (function->is_compiled()) return true; - Handle<Code> code = Compiler::GetUnoptimizedCode(function); - if (code.is_null()) { + MaybeHandle<Code> maybe_code = Compiler::GetUnoptimizedCode(function); + Handle<Code> code; + if (!maybe_code.ToHandle(&code)) { if (flag == CLEAR_EXCEPTION) { function->GetIsolate()->clear_pending_exception(); } @@ -709,7 +706,7 @@ bool Compiler::EnsureCompiled(Handle<JSFunction> function, // full code without debug break slots to full code with debug break slots // depends on the generated code is otherwise exactly the same. // If compilation fails, just keep the existing code. -Handle<Code> Compiler::GetCodeForDebugging(Handle<JSFunction> function) { +MaybeHandle<Code> Compiler::GetCodeForDebugging(Handle<JSFunction> function) { CompilationInfoWithZone info(function); Isolate* isolate = info.isolate(); VMState<COMPILER> state(isolate); @@ -725,18 +722,18 @@ Handle<Code> Compiler::GetCodeForDebugging(Handle<JSFunction> function) { } else { info.MarkNonOptimizable(); } - Handle<Code> new_code = GetUnoptimizedCodeCommon(&info); - if (new_code.is_null()) { + MaybeHandle<Code> maybe_new_code = GetUnoptimizedCodeCommon(&info); + Handle<Code> new_code; + if (!maybe_new_code.ToHandle(&new_code)) { isolate->clear_pending_exception(); } else { ASSERT_EQ(old_code->is_compiled_optimizable(), new_code->is_compiled_optimizable()); } - return new_code; + return maybe_new_code; } -#ifdef ENABLE_DEBUGGER_SUPPORT void Compiler::CompileForLiveEdit(Handle<Script> script) { // TODO(635): support extensions. CompilationInfoWithZone info(script); @@ -756,7 +753,6 @@ void Compiler::CompileForLiveEdit(Handle<Script> script) { } tracker.RecordRootFunctionInfo(info.code()); } -#endif static bool DebuggerWantsEagerCompilation(CompilationInfo* info, @@ -776,9 +772,7 @@ static Handle<SharedFunctionInfo> CompileToplevel(CompilationInfo* info) { FixedArray* array = isolate->native_context()->embedder_data(); script->set_context_data(array->get(0)); -#ifdef ENABLE_DEBUGGER_SUPPORT isolate->debugger()->OnBeforeCompile(script); -#endif ASSERT(info->is_eval() || info->is_global()); @@ -827,7 +821,8 @@ static Handle<SharedFunctionInfo> CompileToplevel(CompilationInfo* info) { lit->materialized_literal_count(), lit->is_generator(), info->code(), - ScopeInfo::Create(info->scope(), info->zone())); + ScopeInfo::Create(info->scope(), info->zone()), + info->feedback_vector()); ASSERT_EQ(RelocInfo::kNoPosition, lit->function_token_position()); SetFunctionInfo(result, lit, true, script); @@ -854,29 +849,30 @@ static Handle<SharedFunctionInfo> CompileToplevel(CompilationInfo* info) { live_edit_tracker.RecordFunctionInfo(result, lit, info->zone()); } -#ifdef ENABLE_DEBUGGER_SUPPORT isolate->debugger()->OnAfterCompile(script, Debugger::NO_AFTER_COMPILE_FLAGS); -#endif return result; } -Handle<JSFunction> Compiler::GetFunctionFromEval(Handle<String> source, - Handle<Context> context, - StrictMode strict_mode, - ParseRestriction restriction, - int scope_position) { +MaybeHandle<JSFunction> Compiler::GetFunctionFromEval( + Handle<String> source, + Handle<Context> context, + StrictMode strict_mode, + ParseRestriction restriction, + int scope_position) { Isolate* isolate = source->GetIsolate(); int source_length = source->length(); isolate->counters()->total_eval_size()->Increment(source_length); isolate->counters()->total_compile_size()->Increment(source_length); CompilationCache* compilation_cache = isolate->compilation_cache(); - Handle<SharedFunctionInfo> shared_info = compilation_cache->LookupEval( - source, context, strict_mode, scope_position); + MaybeHandle<SharedFunctionInfo> maybe_shared_info = + compilation_cache->LookupEval(source, context, strict_mode, + scope_position); + Handle<SharedFunctionInfo> shared_info; - if (shared_info.is_null()) { + if (!maybe_shared_info.ToHandle(&shared_info)) { Handle<Script> script = isolate->factory()->NewScript(source); CompilationInfoWithZone info(script); info.MarkAsEval(); @@ -885,14 +881,12 @@ Handle<JSFunction> Compiler::GetFunctionFromEval(Handle<String> source, info.SetParseRestriction(restriction); info.SetContext(context); -#if ENABLE_DEBUGGER_SUPPORT Debug::RecordEvalCaller(script); -#endif // ENABLE_DEBUGGER_SUPPORT shared_info = CompileToplevel(&info); if (shared_info.is_null()) { - return Handle<JSFunction>::null(); + return MaybeHandle<JSFunction>(); } else { // Explicitly disable optimization for eval code. We're not yet prepared // to handle eval-code in the optimizing compiler. @@ -922,7 +916,7 @@ Handle<SharedFunctionInfo> Compiler::CompileScript( bool is_shared_cross_origin, Handle<Context> context, v8::Extension* extension, - ScriptDataImpl** cached_data, + ScriptData** cached_data, CachedDataMode cached_data_mode, NativesFlag natives) { if (cached_data_mode == NO_CACHED_DATA) { @@ -941,25 +935,16 @@ Handle<SharedFunctionInfo> Compiler::CompileScript( CompilationCache* compilation_cache = isolate->compilation_cache(); // Do a lookup in the compilation cache but not for extensions. + MaybeHandle<SharedFunctionInfo> maybe_result; Handle<SharedFunctionInfo> result; if (extension == NULL) { - result = compilation_cache->LookupScript(source, - script_name, - line_offset, - column_offset, - is_shared_cross_origin, - context); + maybe_result = compilation_cache->LookupScript( + source, script_name, line_offset, column_offset, + is_shared_cross_origin, context); } - if (result.is_null()) { - // No cache entry found. Do pre-parsing, if it makes sense, and compile - // the script. - // Building preparse data that is only used immediately after is only a - // saving if we might skip building the AST for lazily compiled functions. - // I.e., preparse data isn't relevant when the lazy flag is off, and - // 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. + if (!maybe_result.ToHandle(&result)) { + // No cache entry found. Compile the script. // Create a script object describing the script to be compiled. Handle<Script> script = isolate->factory()->NewScript(source); @@ -984,11 +969,10 @@ Handle<SharedFunctionInfo> Compiler::CompileScript( if (extension == NULL && !result.is_null() && !result->dont_cache()) { compilation_cache->PutScript(source, context, result); } + if (result.is_null()) isolate->ReportPendingMessages(); } else if (result->ic_age() != isolate->heap()->global_ic_age()) { result->ResetForNewContext(isolate->heap()->global_ic_age()); } - - if (result.is_null()) isolate->ReportPendingMessages(); return result; } @@ -1036,7 +1020,8 @@ Handle<SharedFunctionInfo> Compiler::BuildFunctionInfo(FunctionLiteral* literal, literal->materialized_literal_count(), literal->is_generator(), info.code(), - scope_info); + scope_info, + info.feedback_vector()); SetFunctionInfo(result, literal, false, script); RecordFunctionCompilation(Logger::FUNCTION_TAG, &info, result); result->set_allows_lazy_compilation(allow_lazy); @@ -1051,8 +1036,9 @@ Handle<SharedFunctionInfo> Compiler::BuildFunctionInfo(FunctionLiteral* literal, } -static Handle<Code> GetCodeFromOptimizedCodeMap(Handle<JSFunction> function, - BailoutId osr_ast_id) { +MUST_USE_RESULT static MaybeHandle<Code> GetCodeFromOptimizedCodeMap( + Handle<JSFunction> function, + BailoutId osr_ast_id) { if (FLAG_cache_optimized_code) { Handle<SharedFunctionInfo> shared(function->shared()); DisallowHeapAllocation no_gc; @@ -1072,7 +1058,7 @@ static Handle<Code> GetCodeFromOptimizedCodeMap(Handle<JSFunction> function, return Handle<Code>(shared->GetCodeFromOptimizedCodeMap(index)); } } - return Handle<Code>::null(); + return MaybeHandle<Code>(); } @@ -1159,12 +1145,15 @@ static bool GetOptimizedCodeLater(CompilationInfo* info) { } -Handle<Code> Compiler::GetOptimizedCode(Handle<JSFunction> function, - Handle<Code> current_code, - ConcurrencyMode mode, - BailoutId osr_ast_id) { - Handle<Code> cached_code = GetCodeFromOptimizedCodeMap(function, osr_ast_id); - if (!cached_code.is_null()) return cached_code; +MaybeHandle<Code> Compiler::GetOptimizedCode(Handle<JSFunction> function, + Handle<Code> current_code, + ConcurrencyMode mode, + BailoutId osr_ast_id) { + Handle<Code> cached_code; + if (GetCodeFromOptimizedCodeMap( + function, osr_ast_id).ToHandle(&cached_code)) { + return cached_code; + } SmartPointer<CompilationInfo> info(new CompilationInfoWithZone(function)); Isolate* isolate = info->isolate(); @@ -1197,7 +1186,7 @@ Handle<Code> Compiler::GetOptimizedCode(Handle<JSFunction> function, } if (isolate->has_pending_exception()) isolate->clear_pending_exception(); - return Handle<Code>::null(); + return MaybeHandle<Code>(); } @@ -1261,12 +1250,13 @@ void Compiler::RecordFunctionCompilation(Logger::LogEventsAndTags tag, info->isolate()->cpu_profiler()->is_profiling()) { Handle<Script> script = info->script(); Handle<Code> code = info->code(); - if (code.is_identical_to(info->isolate()->builtins()->CompileUnoptimized())) + if (code.is_identical_to( + info->isolate()->builtins()->CompileUnoptimized())) { return; - int line_num = GetScriptLineNumber(script, shared->start_position()) + 1; + } + int line_num = Script::GetLineNumber(script, shared->start_position()) + 1; int column_num = - GetScriptColumnNumber(script, shared->start_position()) + 1; - USE(line_num); + Script::GetColumnNumber(script, shared->start_position()) + 1; String* script_name = script->name()->IsString() ? String::cast(script->name()) : info->isolate()->heap()->empty_string(); |