LCOV - code coverage report
Current view: top level - src/runtime - runtime-compiler.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 115 127 90.6 %
Date: 2017-10-20 Functions: 11 19 57.9 %

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

Generated by: LCOV version 1.10