LCOV - code coverage report
Current view: top level - src/runtime - runtime-compiler.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 124 134 92.5 %
Date: 2019-02-19 Functions: 15 23 65.2 %

          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      678857 : RUNTIME_FUNCTION(Runtime_CompileLazy) {
      23      678852 :   HandleScope scope(isolate);
      24             :   DCHECK_EQ(1, args.length());
      25     1357704 :   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      678853 :   StackLimitCheck check(isolate);
      36      678853 :   if (check.JsHasOverflowed(kStackSpaceRequiredForCompilation * KB)) {
      37       26611 :     return isolate->StackOverflow();
      38             :   }
      39      652241 :   IsCompiledScope is_compiled_scope;
      40      652241 :   if (!Compiler::Compile(function, Compiler::KEEP_EXCEPTION,
      41      652240 :                          &is_compiled_scope)) {
      42             :     return ReadOnlyRoots(isolate).exception();
      43             :   }
      44             :   DCHECK(function->is_compiled());
      45      652216 :   return function->code();
      46             : }
      47             : 
      48        8640 : RUNTIME_FUNCTION(Runtime_CompileOptimized_Concurrent) {
      49        8640 :   HandleScope scope(isolate);
      50             :   DCHECK_EQ(1, args.length());
      51       17280 :   CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
      52        8640 :   StackLimitCheck check(isolate);
      53        8640 :   if (check.JsHasOverflowed(kStackSpaceRequiredForCompilation * KB)) {
      54         230 :     return isolate->StackOverflow();
      55             :   }
      56        8410 :   if (!Compiler::CompileOptimized(function, ConcurrencyMode::kConcurrent)) {
      57             :     return ReadOnlyRoots(isolate).exception();
      58             :   }
      59             :   DCHECK(function->is_compiled());
      60        8410 :   return function->code();
      61             : }
      62             : 
      63          76 : RUNTIME_FUNCTION(Runtime_FunctionFirstExecution) {
      64          38 :   HandleScope scope(isolate);
      65          38 :   StackLimitCheck check(isolate);
      66             :   DCHECK_EQ(1, args.length());
      67             : 
      68          76 :   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          76 :   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          38 :   return function->code();
      80             : }
      81             : 
      82      319734 : RUNTIME_FUNCTION(Runtime_CompileOptimized_NotConcurrent) {
      83      319734 :   HandleScope scope(isolate);
      84             :   DCHECK_EQ(1, args.length());
      85      639469 :   CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
      86      319735 :   StackLimitCheck check(isolate);
      87      319735 :   if (check.JsHasOverflowed(kStackSpaceRequiredForCompilation * KB)) {
      88       11176 :     return isolate->StackOverflow();
      89             :   }
      90      308559 :   if (!Compiler::CompileOptimized(function, ConcurrencyMode::kNotConcurrent)) {
      91             :     return ReadOnlyRoots(isolate).exception();
      92             :   }
      93             :   DCHECK(function->is_compiled());
      94      308559 :   return function->code();
      95             : }
      96             : 
      97         118 : RUNTIME_FUNCTION(Runtime_EvictOptimizedCodeSlot) {
      98             :   SealHandleScope scope(isolate);
      99             :   DCHECK_EQ(1, args.length());
     100         236 :   CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
     101             : 
     102             :   DCHECK(function->shared()->is_compiled());
     103             : 
     104         236 :   function->feedback_vector()->EvictOptimizedCodeMarkedForDeoptimization(
     105         354 :       function->shared(), "Runtime_EvictOptimizedCodeSlot");
     106         118 :   return function->code();
     107             : }
     108             : 
     109        4966 : RUNTIME_FUNCTION(Runtime_InstantiateAsmJs) {
     110        4966 :   HandleScope scope(isolate);
     111             :   DCHECK_EQ(args.length(), 4);
     112        9932 :   CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
     113             : 
     114             :   Handle<JSReceiver> stdlib;
     115        9932 :   if (args[1]->IsJSReceiver()) {
     116        3367 :     stdlib = args.at<JSReceiver>(1);
     117             :   }
     118             :   Handle<JSReceiver> foreign;
     119        9932 :   if (args[2]->IsJSReceiver()) {
     120        2399 :     foreign = args.at<JSReceiver>(2);
     121             :   }
     122             :   Handle<JSArrayBuffer> memory;
     123        9932 :   if (args[3]->IsJSArrayBuffer()) {
     124        2187 :     memory = args.at<JSArrayBuffer>(3);
     125             :   }
     126        4966 :   if (function->shared()->HasAsmWasmData()) {
     127        9924 :     Handle<SharedFunctionInfo> shared(function->shared(), isolate);
     128        9924 :     Handle<AsmWasmData> data(shared->asm_wasm_data(), isolate);
     129             :     MaybeHandle<Object> result = AsmJs::InstantiateAsmWasm(
     130        4962 :         isolate, shared, data, stdlib, foreign, memory);
     131        4962 :     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         175 :   if (function->shared()->HasAsmWasmData()) {
     138             :     SharedFunctionInfo::DiscardCompiled(isolate,
     139         342 :                                         handle(function->shared(), isolate));
     140             :   }
     141         175 :   function->shared()->set_is_asm_wasm_broken(true);
     142             :   DCHECK(function->code() ==
     143             :          isolate->builtins()->builtin(Builtins::kInstantiateAsmJs));
     144         350 :   function->set_code(isolate->builtins()->builtin(Builtins::kCompileLazy));
     145        4966 :   return Smi::kZero;
     146             : }
     147             : 
     148       45171 : RUNTIME_FUNCTION(Runtime_NotifyDeoptimized) {
     149       45171 :   HandleScope scope(isolate);
     150             :   DCHECK_EQ(0, args.length());
     151       90342 :   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       90342 :   TimerEventScope<TimerEventDeoptimizeCode> timer(isolate);
     158       90342 :   TRACE_EVENT0("v8", "V8.DeoptimizeCode");
     159       45171 :   Handle<JSFunction> function = deoptimizer->function();
     160       45171 :   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       90342 :   isolate->set_context(deoptimizer->function()->native_context());
     165             : 
     166             :   // Make sure to materialize objects before causing any allocation.
     167       45171 :   deoptimizer->MaterializeHeapObjects();
     168       45171 :   delete deoptimizer;
     169             : 
     170             :   // Ensure the context register is updated for materialized objects.
     171       90342 :   JavaScriptFrameIterator top_it(isolate);
     172       45171 :   JavaScriptFrame* top_frame = top_it.frame();
     173       90342 :   isolate->set_context(Context::cast(top_frame->context()));
     174             : 
     175             :   // Invalidate the underlying optimized code on non-lazy deopts.
     176       45171 :   if (type != DeoptimizeKind::kLazy) {
     177       41244 :     Deoptimizer::DeoptimizeFunction(*function);
     178             :   }
     179             : 
     180       45171 :   return ReadOnlyRoots(isolate).undefined_value();
     181             : }
     182             : 
     183             : 
     184       12303 : static bool IsSuitableForOnStackReplacement(Isolate* isolate,
     185             :                                             Handle<JSFunction> function) {
     186             :   // Keep track of whether we've succeeded in optimizing.
     187       12303 :   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       73712 :   for (JavaScriptFrameIterator it(isolate); !it.done(); it.Advance()) {
     194             :     JavaScriptFrame* frame = it.frame();
     195       49768 :     if (frame->is_optimized() && frame->function() == *function) return false;
     196             :   }
     197             : 
     198       12289 :   return true;
     199             : }
     200             : 
     201             : namespace {
     202             : 
     203       12303 : 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       12303 :   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       12303 :   return BailoutId(iframe->GetBytecodeOffset());
     221             : }
     222             : 
     223             : }  // namespace
     224             : 
     225       12303 : RUNTIME_FUNCTION(Runtime_CompileForOnStackReplacement) {
     226       12303 :   HandleScope scope(isolate);
     227             :   DCHECK_EQ(1, args.length());
     228       24606 :   CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
     229             : 
     230             :   // Only reachable when OST is enabled.
     231       12303 :   CHECK(FLAG_use_osr);
     232             : 
     233             :   // Determine frame triggering OSR request.
     234       24606 :   JavaScriptFrameIterator it(isolate);
     235       12303 :   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       12303 :   BailoutId ast_id = DetermineEntryAndDisarmOSRForInterpreter(frame);
     242             :   DCHECK(!ast_id.IsNone());
     243             : 
     244             :   MaybeHandle<Code> maybe_result;
     245       12303 :   if (IsSuitableForOnStackReplacement(isolate, function)) {
     246       12289 :     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       12289 :     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       29583 :   if (maybe_result.ToHandle(&result) &&
     257       17280 :       result->kind() == Code::OPTIMIZED_FUNCTION) {
     258             :     DeoptimizationData data =
     259        9954 :         DeoptimizationData::cast(result->deoptimization_data());
     260             : 
     261        4977 :     if (data->OsrPcOffset()->value() >= 0) {
     262             :       DCHECK(BailoutId(data->OsrBytecodeOffset()->value()) == ast_id);
     263        4977 :       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        4977 :       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        4705 :         if (FLAG_trace_osr) {
     274           0 :           PrintF("[OSR - Re-marking ");
     275           0 :           function->PrintName();
     276           0 :           PrintF(" for non-concurrent optimization]\n");
     277             :         }
     278        4705 :         function->SetOptimizationMarker(OptimizationMarker::kCompileOptimized);
     279             :       }
     280             :       return *result;
     281             :     }
     282             :   }
     283             : 
     284             :   // Failed.
     285        7326 :   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        7326 :   if (!function->IsOptimized()) {
     292       14652 :     function->set_code(function->shared()->GetCode());
     293             :   }
     294       19629 :   return Object();
     295             : }
     296             : 
     297     2451029 : 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     4902058 :   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     4902109 :   if (native_context->allow_code_gen_from_strings()->IsFalse(isolate) &&
     307             :       !Compiler::CodeGenerationFromStringsAllowed(isolate, native_context,
     308          51 :                                                   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     5007305 :   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     2345662 :   return *compiled;
     329             : }
     330             : 
     331     2451416 : RUNTIME_FUNCTION(Runtime_ResolvePossiblyDirectEval) {
     332     2451416 :   HandleScope scope(isolate);
     333             :   DCHECK_EQ(6, args.length());
     334             : 
     335     2451416 :   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    12256963 :   if (*callee != isolate->native_context()->global_eval_fun() ||
     343     4902715 :       !args[1]->IsString()) {
     344             :     return *callee;
     345             :   }
     346             : 
     347             :   DCHECK(args[3]->IsSmi());
     348             :   DCHECK(is_valid_language_mode(args.smi_at(3)));
     349     2451029 :   LanguageMode language_mode = static_cast<LanguageMode>(args.smi_at(3));
     350             :   DCHECK(args[4]->IsSmi());
     351     4902058 :   Handle<SharedFunctionInfo> outer_info(args.at<JSFunction>(2)->shared(),
     352     4902058 :                                         isolate);
     353             :   return CompileGlobalEval(isolate, args.at<String>(1), outer_info,
     354     2451029 :                            language_mode, args.smi_at(4), args.smi_at(5));
     355             : }
     356             : }  // namespace internal
     357      178779 : }  // namespace v8

Generated by: LCOV version 1.10