LCOV - code coverage report
Current view: top level - src/runtime - runtime-compiler.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 90 100 90.0 %
Date: 2019-04-18 Functions: 14 22 63.6 %

          Line data    Source code
       1             : // Copyright 2014 the V8 project authors. All rights reserved.
       2             : // Use of this source code is governed by a BSD-style license that can be
       3             : // found in the LICENSE file.
       4             : 
       5             : #include "src/arguments-inl.h"
       6             : #include "src/asmjs/asm-js.h"
       7             : #include "src/compiler-dispatcher/optimizing-compile-dispatcher.h"
       8             : #include "src/compiler.h"
       9             : #include "src/deoptimizer.h"
      10             : #include "src/frames-inl.h"
      11             : #include "src/isolate-inl.h"
      12             : #include "src/message-template.h"
      13             : #include "src/objects/js-array-buffer-inl.h"
      14             : #include "src/objects/js-array-inl.h"
      15             : #include "src/runtime/runtime-utils.h"
      16             : #include "src/v8threads.h"
      17             : #include "src/vm-state-inl.h"
      18             : 
      19             : namespace v8 {
      20             : namespace internal {
      21             : 
      22     1366069 : RUNTIME_FUNCTION(Runtime_CompileLazy) {
      23             :   HandleScope scope(isolate);
      24             :   DCHECK_EQ(1, args.length());
      25      683034 :   CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
      26             : 
      27             : #ifdef DEBUG
      28             :   if (FLAG_trace_lazy && !function->shared()->is_compiled()) {
      29             :     PrintF("[unoptimized: ");
      30             :     function->PrintName();
      31             :     PrintF("]\n");
      32             :   }
      33             : #endif
      34             : 
      35             :   StackLimitCheck check(isolate);
      36      683033 :   if (check.JsHasOverflowed(kStackSpaceRequiredForCompilation * KB)) {
      37       26647 :     return isolate->StackOverflow();
      38             :   }
      39             :   IsCompiledScope is_compiled_scope;
      40      656386 :   if (!Compiler::Compile(function, Compiler::KEEP_EXCEPTION,
      41             :                          &is_compiled_scope)) {
      42             :     return ReadOnlyRoots(isolate).exception();
      43             :   }
      44             :   DCHECK(function->is_compiled());
      45      656363 :   return function->code();
      46             : }
      47             : 
      48       16572 : RUNTIME_FUNCTION(Runtime_CompileOptimized_Concurrent) {
      49             :   HandleScope scope(isolate);
      50             :   DCHECK_EQ(1, args.length());
      51        8286 :   CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
      52             :   StackLimitCheck check(isolate);
      53        8286 :   if (check.JsHasOverflowed(kStackSpaceRequiredForCompilation * KB)) {
      54         195 :     return isolate->StackOverflow();
      55             :   }
      56        8091 :   if (!Compiler::CompileOptimized(function, ConcurrencyMode::kConcurrent)) {
      57             :     return ReadOnlyRoots(isolate).exception();
      58             :   }
      59             :   DCHECK(function->is_compiled());
      60        8091 :   return function->code();
      61             : }
      62             : 
      63          76 : RUNTIME_FUNCTION(Runtime_FunctionFirstExecution) {
      64             :   HandleScope scope(isolate);
      65             :   StackLimitCheck check(isolate);
      66             :   DCHECK_EQ(1, args.length());
      67             : 
      68          38 :   CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
      69             :   DCHECK_EQ(function->feedback_vector()->optimization_marker(),
      70             :             OptimizationMarker::kLogFirstExecution);
      71             :   DCHECK(FLAG_log_function_events);
      72             :   Handle<SharedFunctionInfo> sfi(function->shared(), isolate);
      73         228 :   LOG(isolate, FunctionEvent(
      74             :                    "first-execution", Script::cast(sfi->script())->id(), 0,
      75             :                    sfi->StartPosition(), sfi->EndPosition(), sfi->DebugName()));
      76          38 :   function->feedback_vector()->ClearOptimizationMarker();
      77             :   // Return the code to continue execution, we don't care at this point whether
      78             :   // this is for lazy compilation or has been eagerly complied.
      79             :   return function->code();
      80             : }
      81             : 
      82      654702 : RUNTIME_FUNCTION(Runtime_CompileOptimized_NotConcurrent) {
      83             :   HandleScope scope(isolate);
      84             :   DCHECK_EQ(1, args.length());
      85      327351 :   CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
      86             :   StackLimitCheck check(isolate);
      87      327352 :   if (check.JsHasOverflowed(kStackSpaceRequiredForCompilation * KB)) {
      88       11177 :     return isolate->StackOverflow();
      89             :   }
      90      316175 :   if (!Compiler::CompileOptimized(function, ConcurrencyMode::kNotConcurrent)) {
      91             :     return ReadOnlyRoots(isolate).exception();
      92             :   }
      93             :   DCHECK(function->is_compiled());
      94      316176 :   return function->code();
      95             : }
      96             : 
      97         234 : RUNTIME_FUNCTION(Runtime_EvictOptimizedCodeSlot) {
      98             :   SealHandleScope scope(isolate);
      99             :   DCHECK_EQ(1, args.length());
     100         117 :   CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
     101             : 
     102             :   DCHECK(function->shared()->is_compiled());
     103             : 
     104         351 :   function->feedback_vector()->EvictOptimizedCodeMarkedForDeoptimization(
     105         117 :       function->shared(), "Runtime_EvictOptimizedCodeSlot");
     106         117 :   return function->code();
     107             : }
     108             : 
     109       10046 : RUNTIME_FUNCTION(Runtime_InstantiateAsmJs) {
     110             :   HandleScope scope(isolate);
     111             :   DCHECK_EQ(args.length(), 4);
     112        5023 :   CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
     113             : 
     114             :   Handle<JSReceiver> stdlib;
     115        5023 :   if (args[1]->IsJSReceiver()) {
     116             :     stdlib = args.at<JSReceiver>(1);
     117             :   }
     118             :   Handle<JSReceiver> foreign;
     119        5023 :   if (args[2]->IsJSReceiver()) {
     120             :     foreign = args.at<JSReceiver>(2);
     121             :   }
     122             :   Handle<JSArrayBuffer> memory;
     123        5023 :   if (args[3]->IsJSArrayBuffer()) {
     124        2188 :     memory = args.at<JSArrayBuffer>(3);
     125             :   }
     126        5023 :   if (function->shared()->HasAsmWasmData()) {
     127             :     Handle<SharedFunctionInfo> shared(function->shared(), isolate);
     128             :     Handle<AsmWasmData> data(shared->asm_wasm_data(), isolate);
     129             :     MaybeHandle<Object> result = AsmJs::InstantiateAsmWasm(
     130        5019 :         isolate, shared, data, stdlib, foreign, memory);
     131        5019 :     if (!result.is_null()) {
     132             :       return *result.ToHandleChecked();
     133             :     }
     134             :   }
     135             :   // Remove wasm data, mark as broken for asm->wasm, replace function code with
     136             :   // UncompiledData, and return a smi 0 to indicate failure.
     137         176 :   if (function->shared()->HasAsmWasmData()) {
     138             :     SharedFunctionInfo::DiscardCompiled(isolate,
     139         172 :                                         handle(function->shared(), isolate));
     140             :   }
     141         176 :   function->shared()->set_is_asm_wasm_broken(true);
     142             :   DCHECK(function->code() ==
     143             :          isolate->builtins()->builtin(Builtins::kInstantiateAsmJs));
     144         352 :   function->set_code(isolate->builtins()->builtin(Builtins::kCompileLazy));
     145             :   return Smi::kZero;
     146             : }
     147             : 
     148      108478 : RUNTIME_FUNCTION(Runtime_NotifyDeoptimized) {
     149             :   HandleScope scope(isolate);
     150             :   DCHECK_EQ(0, args.length());
     151       54239 :   Deoptimizer* deoptimizer = Deoptimizer::Grab(isolate);
     152             :   DCHECK(deoptimizer->compiled_code()->kind() == Code::OPTIMIZED_FUNCTION);
     153             :   DCHECK(deoptimizer->compiled_code()->is_turbofanned());
     154             :   DCHECK(AllowHeapAllocation::IsAllowed());
     155             :   DCHECK(isolate->context().is_null());
     156             : 
     157             :   TimerEventScope<TimerEventDeoptimizeCode> timer(isolate);
     158      162717 :   TRACE_EVENT0("v8", "V8.DeoptimizeCode");
     159       54239 :   Handle<JSFunction> function = deoptimizer->function();
     160             :   DeoptimizeKind type = deoptimizer->deopt_kind();
     161             : 
     162             :   // TODO(turbofan): We currently need the native context to materialize
     163             :   // the arguments object, but only to get to its map.
     164      108478 :   isolate->set_context(deoptimizer->function()->native_context());
     165             : 
     166             :   // Make sure to materialize objects before causing any allocation.
     167       54239 :   deoptimizer->MaterializeHeapObjects();
     168       54239 :   delete deoptimizer;
     169             : 
     170             :   // Ensure the context register is updated for materialized objects.
     171       54239 :   JavaScriptFrameIterator top_it(isolate);
     172             :   JavaScriptFrame* top_frame = top_it.frame();
     173       54239 :   isolate->set_context(Context::cast(top_frame->context()));
     174             : 
     175             :   // Invalidate the underlying optimized code on non-lazy deopts.
     176       54239 :   if (type != DeoptimizeKind::kLazy) {
     177       20701 :     Deoptimizer::DeoptimizeFunction(*function);
     178             :   }
     179             : 
     180             :   return ReadOnlyRoots(isolate).undefined_value();
     181             : }
     182             : 
     183             : 
     184       11897 : static bool IsSuitableForOnStackReplacement(Isolate* isolate,
     185             :                                             Handle<JSFunction> function) {
     186             :   // Keep track of whether we've succeeded in optimizing.
     187       11897 :   if (function->shared()->optimization_disabled()) return false;
     188             :   // If we are trying to do OSR when there are already optimized
     189             :   // activations of the function, it means (a) the function is directly or
     190             :   // indirectly recursive and (b) an optimized invocation has been
     191             :   // deoptimized so that we are currently in an unoptimized activation.
     192             :   // Check for optimized activations of this function.
     193       34290 :   for (JavaScriptFrameIterator it(isolate); !it.done(); it.Advance()) {
     194             :     JavaScriptFrame* frame = it.frame();
     195       45274 :     if (frame->is_optimized() && frame->function() == *function) return false;
     196             :   }
     197             : 
     198       11897 :   return true;
     199             : }
     200             : 
     201             : namespace {
     202             : 
     203       11897 : BailoutId DetermineEntryAndDisarmOSRForInterpreter(JavaScriptFrame* frame) {
     204             :   InterpretedFrame* iframe = reinterpret_cast<InterpretedFrame*>(frame);
     205             : 
     206             :   // Note that the bytecode array active on the stack might be different from
     207             :   // the one installed on the function (e.g. patched by debugger). This however
     208             :   // is fine because we guarantee the layout to be in sync, hence any BailoutId
     209             :   // representing the entry point will be valid for any copy of the bytecode.
     210       11897 :   Handle<BytecodeArray> bytecode(iframe->GetBytecodeArray(), iframe->isolate());
     211             : 
     212             :   DCHECK(frame->LookupCode()->is_interpreter_trampoline_builtin());
     213             :   DCHECK(frame->function()->shared()->HasBytecodeArray());
     214             :   DCHECK(frame->is_interpreted());
     215             : 
     216             :   // Reset the OSR loop nesting depth to disarm back edges.
     217             :   bytecode->set_osr_loop_nesting_level(0);
     218             : 
     219             :   // Return a BailoutId representing the bytecode offset of the back branch.
     220       11897 :   return BailoutId(iframe->GetBytecodeOffset());
     221             : }
     222             : 
     223             : }  // namespace
     224             : 
     225       23794 : RUNTIME_FUNCTION(Runtime_CompileForOnStackReplacement) {
     226             :   HandleScope scope(isolate);
     227             :   DCHECK_EQ(1, args.length());
     228       11897 :   CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
     229             : 
     230             :   // Only reachable when OST is enabled.
     231       11897 :   CHECK(FLAG_use_osr);
     232             : 
     233             :   // Determine frame triggering OSR request.
     234       11897 :   JavaScriptFrameIterator it(isolate);
     235             :   JavaScriptFrame* frame = it.frame();
     236             :   DCHECK_EQ(frame->function(), *function);
     237             :   DCHECK(frame->is_interpreted());
     238             : 
     239             :   // Determine the entry point for which this OSR request has been fired and
     240             :   // also disarm all back edges in the calling code to stop new requests.
     241       11897 :   BailoutId ast_id = DetermineEntryAndDisarmOSRForInterpreter(frame);
     242             :   DCHECK(!ast_id.IsNone());
     243             : 
     244             :   MaybeHandle<Code> maybe_result;
     245       11897 :   if (IsSuitableForOnStackReplacement(isolate, function)) {
     246       11897 :     if (FLAG_trace_osr) {
     247           0 :       PrintF("[OSR - Compiling: ");
     248           0 :       function->PrintName();
     249           0 :       PrintF(" at AST id %d]\n", ast_id.ToInt());
     250             :     }
     251       11897 :     maybe_result = Compiler::GetOptimizedCodeForOSR(function, ast_id, frame);
     252             :   }
     253             : 
     254             :   // Check whether we ended up with usable optimized code.
     255             :   Handle<Code> result;
     256       16512 :   if (maybe_result.ToHandle(&result) &&
     257             :       result->kind() == Code::OPTIMIZED_FUNCTION) {
     258             :     DeoptimizationData data =
     259        4615 :         DeoptimizationData::cast(result->deoptimization_data());
     260             : 
     261        9230 :     if (data->OsrPcOffset()->value() >= 0) {
     262             :       DCHECK(BailoutId(data->OsrBytecodeOffset()->value()) == ast_id);
     263        4615 :       if (FLAG_trace_osr) {
     264             :         PrintF("[OSR - Entry at AST id %d, offset %d in optimized code]\n",
     265           0 :                ast_id.ToInt(), data->OsrPcOffset()->value());
     266             :       }
     267             : 
     268             :       DCHECK(result->is_turbofanned());
     269        4615 :       if (!function->HasOptimizedCode()) {
     270             :         // If we're not already optimized, set to optimize non-concurrently on
     271             :         // the next call, otherwise we'd run unoptimized once more and
     272             :         // potentially compile for OSR again.
     273        4440 :         if (FLAG_trace_osr) {
     274           0 :           PrintF("[OSR - Re-marking ");
     275           0 :           function->PrintName();
     276           0 :           PrintF(" for non-concurrent optimization]\n");
     277             :         }
     278             :         function->SetOptimizationMarker(OptimizationMarker::kCompileOptimized);
     279             :       }
     280             :       return *result;
     281             :     }
     282             :   }
     283             : 
     284             :   // Failed.
     285        7282 :   if (FLAG_trace_osr) {
     286           0 :     PrintF("[OSR - Failed: ");
     287           0 :     function->PrintName();
     288           0 :     PrintF(" at AST id %d]\n", ast_id.ToInt());
     289             :   }
     290             : 
     291        7282 :   if (!function->IsOptimized()) {
     292       14564 :     function->set_code(function->shared()->GetCode());
     293             :   }
     294             :   return Object();
     295             : }
     296             : 
     297     2453791 : static Object CompileGlobalEval(Isolate* isolate, Handle<String> source,
     298             :                                 Handle<SharedFunctionInfo> outer_info,
     299             :                                 LanguageMode language_mode,
     300             :                                 int eval_scope_position, int eval_position) {
     301             :   Handle<Context> context(isolate->context(), isolate);
     302             :   Handle<Context> native_context(context->native_context(), isolate);
     303             : 
     304             :   // Check if native context allows code generation from
     305             :   // strings. Throw an exception if it doesn't.
     306     4907633 :   if (native_context->allow_code_gen_from_strings()->IsFalse(isolate) &&
     307          51 :       !Compiler::CodeGenerationFromStringsAllowed(isolate, native_context,
     308             :                                                   source)) {
     309             :     Handle<Object> error_message =
     310          40 :         native_context->ErrorMessageForCodeGenerationFromStrings();
     311             :     Handle<Object> error;
     312             :     MaybeHandle<Object> maybe_error = isolate->factory()->NewEvalError(
     313          40 :         MessageTemplate::kCodeGenFromStrings, error_message);
     314          80 :     if (maybe_error.ToHandle(&error)) isolate->Throw(*error);
     315          40 :     return ReadOnlyRoots(isolate).exception();
     316             :   }
     317             : 
     318             :   // Deal with a normal eval call with a string argument. Compile it
     319             :   // and return the compiled function bound in the local context.
     320             :   static const ParseRestriction restriction = NO_PARSE_RESTRICTION;
     321             :   Handle<JSFunction> compiled;
     322     5012879 :   ASSIGN_RETURN_ON_EXCEPTION_VALUE(
     323             :       isolate, compiled,
     324             :       Compiler::GetFunctionFromEval(source, outer_info, context, language_mode,
     325             :                                     restriction, kNoSourcePosition,
     326             :                                     eval_scope_position, eval_position),
     327             :       ReadOnlyRoots(isolate).exception());
     328     2348374 :   return *compiled;
     329             : }
     330             : 
     331     4908356 : RUNTIME_FUNCTION(Runtime_ResolvePossiblyDirectEval) {
     332             :   HandleScope scope(isolate);
     333             :   DCHECK_EQ(6, args.length());
     334             : 
     335             :   Handle<Object> callee = args.at(0);
     336             : 
     337             :   // If "eval" didn't refer to the original GlobalEval, it's not a
     338             :   // direct call to eval.
     339             :   // (And even if it is, but the first argument isn't a string, just let
     340             :   // execution default to an indirect call to eval, which will also return
     341             :   // the first argument without doing anything).
     342     9816595 :   if (*callee != isolate->native_context()->global_eval_fun() ||
     343             :       !args[1]->IsString()) {
     344             :     return *callee;
     345             :   }
     346             : 
     347             :   DCHECK(args[3]->IsSmi());
     348             :   DCHECK(is_valid_language_mode(args.smi_at(3)));
     349     2453791 :   LanguageMode language_mode = static_cast<LanguageMode>(args.smi_at(3));
     350             :   DCHECK(args[4]->IsSmi());
     351             :   Handle<SharedFunctionInfo> outer_info(args.at<JSFunction>(2)->shared(),
     352             :                                         isolate);
     353             :   return CompileGlobalEval(isolate, args.at<String>(1), outer_info,
     354     2453791 :                            language_mode, args.smi_at(4), args.smi_at(5));
     355             : }
     356             : }  // namespace internal
     357      122036 : }  // namespace v8

Generated by: LCOV version 1.10