LCOV - code coverage report
Current view: top level - src/builtins - setup-builtins-internal.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 131 138 94.9 %
Date: 2019-02-19 Functions: 14 14 100.0 %

          Line data    Source code
       1             : // Copyright 2017 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/setup-isolate.h"
       6             : 
       7             : #include "src/assembler-inl.h"
       8             : #include "src/builtins/builtins.h"
       9             : #include "src/code-events.h"
      10             : #include "src/compiler/code-assembler.h"
      11             : #include "src/handles-inl.h"
      12             : #include "src/heap/heap-inl.h"  // For MemoryAllocator::code_range.
      13             : #include "src/interface-descriptors.h"
      14             : #include "src/interpreter/bytecodes.h"
      15             : #include "src/interpreter/interpreter-generator.h"
      16             : #include "src/interpreter/interpreter.h"
      17             : #include "src/isolate.h"
      18             : #include "src/macro-assembler.h"
      19             : #include "src/objects-inl.h"
      20             : #include "src/objects/shared-function-info.h"
      21             : #include "src/objects/smi.h"
      22             : 
      23             : namespace v8 {
      24             : namespace internal {
      25             : 
      26             : // Forward declarations for C++ builtins.
      27             : #define FORWARD_DECLARE(Name) \
      28             :   Address Builtin_##Name(int argc, Address* args, Isolate* isolate);
      29             : BUILTIN_LIST_C(FORWARD_DECLARE)
      30             : #undef FORWARD_DECLARE
      31             : 
      32             : namespace {
      33             : 
      34       84280 : void PostBuildProfileAndTracing(Isolate* isolate, Code code, const char* name) {
      35       84280 :   PROFILE(isolate, CodeCreateEvent(CodeEventListener::BUILTIN_TAG,
      36             :                                    AbstractCode::cast(code), name));
      37       84280 : }
      38             : 
      39       84280 : AssemblerOptions BuiltinAssemblerOptions(Isolate* isolate,
      40             :                                          int32_t builtin_index) {
      41       84280 :   AssemblerOptions options = AssemblerOptions::Default(isolate);
      42       84280 :   CHECK(!options.isolate_independent_code);
      43       84280 :   CHECK(!options.use_pc_relative_calls_and_jumps);
      44             : 
      45      168560 :   if (!isolate->ShouldLoadConstantsFromRootList() ||
      46       84280 :       !Builtins::IsIsolateIndependent(builtin_index)) {
      47           0 :     return options;
      48             :   }
      49             : 
      50             :   const base::AddressRegion& code_range =
      51       84280 :       isolate->heap()->memory_allocator()->code_range();
      52             :   bool pc_relative_calls_fit_in_code_range =
      53      168560 :       !code_range.is_empty() &&
      54       84280 :       std::ceil(static_cast<float>(code_range.size() / MB)) <=
      55       84280 :           kMaxPCRelativeCodeRangeInMB;
      56             : 
      57       84280 :   options.isolate_independent_code = true;
      58       84280 :   options.use_pc_relative_calls_and_jumps = pc_relative_calls_fit_in_code_range;
      59             : 
      60       84280 :   return options;
      61             : }
      62             : 
      63             : typedef void (*MacroAssemblerGenerator)(MacroAssembler*);
      64             : typedef void (*CodeAssemblerGenerator)(compiler::CodeAssemblerState*);
      65             : 
      66       84280 : Handle<Code> BuildPlaceholder(Isolate* isolate, int32_t builtin_index) {
      67       84280 :   HandleScope scope(isolate);
      68       84280 :   constexpr int kBufferSize = 1 * KB;
      69             :   byte buffer[kBufferSize];
      70             :   MacroAssembler masm(isolate, CodeObjectRequired::kYes,
      71      168560 :                       ExternalAssemblerBuffer(buffer, kBufferSize));
      72             :   DCHECK(!masm.has_frame());
      73             :   {
      74       84280 :     FrameScope scope(&masm, StackFrame::NONE);
      75             :     // The contents of placeholder don't matter, as long as they don't create
      76             :     // embedded constants or external references.
      77       84280 :     masm.Move(kJavaScriptCallCodeStartRegister, Smi::zero());
      78       84280 :     masm.Call(kJavaScriptCallCodeStartRegister);
      79             :   }
      80       84280 :   CodeDesc desc;
      81       84280 :   masm.GetCode(isolate, &desc);
      82             :   Handle<Code> code = isolate->factory()->NewCode(
      83      337120 :       desc, Code::BUILTIN, masm.CodeObject(), builtin_index);
      84      168560 :   return scope.CloseAndEscape(code);
      85             : }
      86             : 
      87        3920 : Code BuildWithMacroAssembler(Isolate* isolate, int32_t builtin_index,
      88             :                              MacroAssemblerGenerator generator,
      89             :                              const char* s_name) {
      90        3920 :   HandleScope scope(isolate);
      91             :   // Canonicalize handles, so that we can share constant pool entries pointing
      92             :   // to code targets without dereferencing their handles.
      93        7840 :   CanonicalHandleScope canonical(isolate);
      94        3920 :   constexpr int kBufferSize = 32 * KB;
      95             :   byte buffer[kBufferSize];
      96             : 
      97        3920 :   MacroAssembler masm(isolate, BuiltinAssemblerOptions(isolate, builtin_index),
      98             :                       CodeObjectRequired::kYes,
      99       11760 :                       ExternalAssemblerBuffer(buffer, kBufferSize));
     100        3920 :   masm.set_builtin_index(builtin_index);
     101             :   DCHECK(!masm.has_frame());
     102        3920 :   generator(&masm);
     103             : 
     104        3920 :   int handler_table_offset = 0;
     105             : 
     106             :   // JSEntry builtins are a special case and need to generate a handler table.
     107             :   DCHECK_EQ(Builtins::KindOf(Builtins::kJSEntry), Builtins::ASM);
     108             :   DCHECK_EQ(Builtins::KindOf(Builtins::kJSConstructEntry), Builtins::ASM);
     109             :   DCHECK_EQ(Builtins::KindOf(Builtins::kJSRunMicrotasksEntry), Builtins::ASM);
     110        3920 :   if (Builtins::IsJSEntryVariant(builtin_index)) {
     111             :     static constexpr int kJSEntryHandlerCount = 1;
     112             :     handler_table_offset =
     113         168 :         HandlerTable::EmitReturnTableStart(&masm, kJSEntryHandlerCount);
     114             :     HandlerTable::EmitReturnEntry(
     115         168 :         &masm, 0, isolate->builtins()->js_entry_handler_offset());
     116             :   }
     117             : 
     118        3920 :   CodeDesc desc;
     119             :   masm.GetCode(isolate, &desc, MacroAssembler::kNoSafepointTable,
     120        3920 :                handler_table_offset);
     121             : 
     122             :   static constexpr bool kIsNotTurbofanned = false;
     123             :   static constexpr int kStackSlots = 0;
     124             : 
     125             :   Handle<Code> code = isolate->factory()->NewCode(
     126             :       desc, Code::BUILTIN, masm.CodeObject(), builtin_index,
     127             :       MaybeHandle<ByteArray>(), DeoptimizationData::Empty(isolate), kMovable,
     128       15680 :       kIsNotTurbofanned, kStackSlots);
     129        3920 :   PostBuildProfileAndTracing(isolate, *code, s_name);
     130        3920 :   return *code;
     131             : }
     132             : 
     133       15456 : Code BuildAdaptor(Isolate* isolate, int32_t builtin_index,
     134             :                   Address builtin_address,
     135             :                   Builtins::ExitFrameType exit_frame_type, const char* name) {
     136       15456 :   HandleScope scope(isolate);
     137             :   // Canonicalize handles, so that we can share constant pool entries pointing
     138             :   // to code targets without dereferencing their handles.
     139       30912 :   CanonicalHandleScope canonical(isolate);
     140       15456 :   constexpr int kBufferSize = 32 * KB;
     141             :   byte buffer[kBufferSize];
     142       15456 :   MacroAssembler masm(isolate, BuiltinAssemblerOptions(isolate, builtin_index),
     143             :                       CodeObjectRequired::kYes,
     144       46368 :                       ExternalAssemblerBuffer(buffer, kBufferSize));
     145       15456 :   masm.set_builtin_index(builtin_index);
     146             :   DCHECK(!masm.has_frame());
     147       15456 :   Builtins::Generate_Adaptor(&masm, builtin_address, exit_frame_type);
     148       15456 :   CodeDesc desc;
     149       15456 :   masm.GetCode(isolate, &desc);
     150             :   Handle<Code> code = isolate->factory()->NewCode(
     151       61824 :       desc, Code::BUILTIN, masm.CodeObject(), builtin_index);
     152       15456 :   PostBuildProfileAndTracing(isolate, *code, name);
     153       15456 :   return *code;
     154             : }
     155             : 
     156             : // Builder for builtins implemented in TurboFan with JS linkage.
     157       19040 : Code BuildWithCodeStubAssemblerJS(Isolate* isolate, int32_t builtin_index,
     158             :                                   CodeAssemblerGenerator generator, int argc,
     159             :                                   const char* name) {
     160       19040 :   HandleScope scope(isolate);
     161             :   // Canonicalize handles, so that we can share constant pool entries pointing
     162             :   // to code targets without dereferencing their handles.
     163       38080 :   CanonicalHandleScope canonical(isolate);
     164             : 
     165       19040 :   SegmentSize segment_size = isolate->serializer_enabled()
     166             :                                  ? SegmentSize::kLarge
     167       19040 :                                  : SegmentSize::kDefault;
     168       38080 :   Zone zone(isolate->allocator(), ZONE_NAME, segment_size);
     169             :   const int argc_with_recv =
     170       19040 :       (argc == SharedFunctionInfo::kDontAdaptArgumentsSentinel) ? 0 : argc + 1;
     171             :   compiler::CodeAssemblerState state(
     172             :       isolate, &zone, argc_with_recv, Code::BUILTIN, name,
     173       38080 :       PoisoningMitigationLevel::kDontPoison, builtin_index);
     174       19040 :   generator(&state);
     175             :   Handle<Code> code = compiler::CodeAssembler::GenerateCode(
     176       19040 :       &state, BuiltinAssemblerOptions(isolate, builtin_index));
     177       19040 :   PostBuildProfileAndTracing(isolate, *code, name);
     178       19040 :   return *code;
     179             : }
     180             : 
     181             : // Builder for builtins implemented in TurboFan with CallStub linkage.
     182       19320 : Code BuildWithCodeStubAssemblerCS(Isolate* isolate, int32_t builtin_index,
     183             :                                   CodeAssemblerGenerator generator,
     184             :                                   CallDescriptors::Key interface_descriptor,
     185             :                                   const char* name, int result_size) {
     186       19320 :   HandleScope scope(isolate);
     187             :   // Canonicalize handles, so that we can share constant pool entries pointing
     188             :   // to code targets without dereferencing their handles.
     189       38640 :   CanonicalHandleScope canonical(isolate);
     190       19320 :   SegmentSize segment_size = isolate->serializer_enabled()
     191             :                                  ? SegmentSize::kLarge
     192       19320 :                                  : SegmentSize::kDefault;
     193       38640 :   Zone zone(isolate->allocator(), ZONE_NAME, segment_size);
     194             :   // The interface descriptor with given key must be initialized at this point
     195             :   // and this construction just queries the details from the descriptors table.
     196       38640 :   CallInterfaceDescriptor descriptor(interface_descriptor);
     197             :   // Ensure descriptor is already initialized.
     198             :   DCHECK_EQ(result_size, descriptor.GetReturnCount());
     199             :   DCHECK_LE(0, descriptor.GetRegisterParameterCount());
     200             :   compiler::CodeAssemblerState state(
     201             :       isolate, &zone, descriptor, Code::BUILTIN, name,
     202       38640 :       PoisoningMitigationLevel::kDontPoison, builtin_index);
     203       19320 :   generator(&state);
     204             :   Handle<Code> code = compiler::CodeAssembler::GenerateCode(
     205       19320 :       &state, BuiltinAssemblerOptions(isolate, builtin_index));
     206       19320 :   PostBuildProfileAndTracing(isolate, *code, name);
     207       19320 :   return *code;
     208             : }
     209             : 
     210             : }  // anonymous namespace
     211             : 
     212             : // static
     213      168560 : void SetupIsolateDelegate::AddBuiltin(Builtins* builtins, int index,
     214             :                                       Code code) {
     215             :   DCHECK_EQ(index, code->builtin_index());
     216      168560 :   builtins->set_builtin(index, code);
     217      168560 : }
     218             : 
     219             : // static
     220          56 : void SetupIsolateDelegate::PopulateWithPlaceholders(Isolate* isolate) {
     221             :   // Fill the builtins list with placeholders. References to these placeholder
     222             :   // builtins are eventually replaced by the actual builtins. This is to
     223             :   // support circular references between builtins.
     224          56 :   Builtins* builtins = isolate->builtins();
     225          56 :   HandleScope scope(isolate);
     226       84336 :   for (int i = 0; i < Builtins::builtin_count; i++) {
     227       84280 :     Handle<Code> placeholder = BuildPlaceholder(isolate, i);
     228       84280 :     AddBuiltin(builtins, i, *placeholder);
     229          56 :   }
     230          56 : }
     231             : 
     232             : // static
     233          56 : void SetupIsolateDelegate::ReplacePlaceholders(Isolate* isolate) {
     234             :   // Replace references from all code objects to placeholders.
     235          56 :   Builtins* builtins = isolate->builtins();
     236          56 :   DisallowHeapAllocation no_gc;
     237          56 :   CodeSpaceMemoryModificationScope modification_scope(isolate->heap());
     238             :   static const int kRelocMask =
     239             :       RelocInfo::ModeMask(RelocInfo::CODE_TARGET) |
     240             :       RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT) |
     241             :       RelocInfo::ModeMask(RelocInfo::RELATIVE_CODE_TARGET);
     242         112 :   HeapIterator iterator(isolate->heap());
     243      566776 :   for (HeapObject obj = iterator.next(); !obj.is_null();
     244             :        obj = iterator.next()) {
     245     1133440 :     if (!obj->IsCode()) continue;
     246      168560 :     Code code = Code::cast(obj);
     247      168560 :     bool flush_icache = false;
     248      584752 :     for (RelocIterator it(code, kRelocMask); !it.done(); it.next()) {
     249      416192 :       RelocInfo* rinfo = it.rinfo();
     250      416192 :       if (RelocInfo::IsCodeTargetMode(rinfo->rmode())) {
     251      416192 :         Code target = Code::GetCodeFromTargetAddress(rinfo->target_address());
     252             :         DCHECK_IMPLIES(RelocInfo::IsRelativeCodeTarget(rinfo->rmode()),
     253             :                        Builtins::IsIsolateIndependent(target->builtin_index()));
     254      416192 :         if (!target->is_builtin()) continue;
     255      416192 :         Code new_target = builtins->builtin(target->builtin_index());
     256             :         rinfo->set_target_address(new_target->raw_instruction_start(),
     257      416192 :                                   UPDATE_WRITE_BARRIER, SKIP_ICACHE_FLUSH);
     258             :       } else {
     259             :         DCHECK(RelocInfo::IsEmbeddedObject(rinfo->rmode()));
     260           0 :         Object object = rinfo->target_object();
     261           0 :         if (!object->IsCode()) continue;
     262           0 :         Code target = Code::cast(object);
     263           0 :         if (!target->is_builtin()) continue;
     264           0 :         Code new_target = builtins->builtin(target->builtin_index());
     265             :         rinfo->set_target_object(isolate->heap(), new_target,
     266           0 :                                  UPDATE_WRITE_BARRIER, SKIP_ICACHE_FLUSH);
     267             :       }
     268      416192 :       flush_icache = true;
     269             :     }
     270      168560 :     if (flush_icache) {
     271             :       FlushInstructionCache(code->raw_instruction_start(),
     272       72744 :                             code->raw_instruction_size());
     273             :     }
     274          56 :   }
     275          56 : }
     276             : 
     277             : namespace {
     278             : 
     279       26544 : Code GenerateBytecodeHandler(Isolate* isolate, int builtin_index,
     280             :                              const char* name,
     281             :                              interpreter::OperandScale operand_scale,
     282             :                              interpreter::Bytecode bytecode) {
     283             :   DCHECK(interpreter::Bytecodes::BytecodeHasHandler(bytecode, operand_scale));
     284             : 
     285             :   Handle<Code> code = interpreter::GenerateBytecodeHandler(
     286             :       isolate, bytecode, operand_scale, builtin_index,
     287       26544 :       BuiltinAssemblerOptions(isolate, builtin_index));
     288             : 
     289       26544 :   PostBuildProfileAndTracing(isolate, *code, name);
     290             : 
     291       26544 :   return *code;
     292             : }
     293             : 
     294             : }  // namespace
     295             : 
     296             : // static
     297          56 : void SetupIsolateDelegate::SetupBuiltinsInternal(Isolate* isolate) {
     298          56 :   Builtins* builtins = isolate->builtins();
     299             :   DCHECK(!builtins->initialized_);
     300             : 
     301          56 :   PopulateWithPlaceholders(isolate);
     302             : 
     303             :   // Create a scope for the handles in the builtins.
     304          56 :   HandleScope scope(isolate);
     305             : 
     306          56 :   int index = 0;
     307          56 :   Code code;
     308             : #define BUILD_CPP(Name)                                              \
     309             :   code = BuildAdaptor(isolate, index, FUNCTION_ADDR(Builtin_##Name), \
     310             :                       Builtins::BUILTIN_EXIT, #Name);                \
     311             :   AddBuiltin(builtins, index++, code);
     312             : #define BUILD_API(Name)                                              \
     313             :   code = BuildAdaptor(isolate, index, FUNCTION_ADDR(Builtin_##Name), \
     314             :                       Builtins::EXIT, #Name);                        \
     315             :   AddBuiltin(builtins, index++, code);
     316             : #define BUILD_TFJ(Name, Argc, ...)                              \
     317             :   code = BuildWithCodeStubAssemblerJS(                          \
     318             :       isolate, index, &Builtins::Generate_##Name, Argc, #Name); \
     319             :   AddBuiltin(builtins, index++, code);
     320             : #define BUILD_TFC(Name, InterfaceDescriptor, result_size)        \
     321             :   code = BuildWithCodeStubAssemblerCS(                           \
     322             :       isolate, index, &Builtins::Generate_##Name,                \
     323             :       CallDescriptors::InterfaceDescriptor, #Name, result_size); \
     324             :   AddBuiltin(builtins, index++, code);
     325             : #define BUILD_TFS(Name, ...)                                                   \
     326             :   /* Return size for generic TF builtins (stub linkage) is always 1. */        \
     327             :   code =                                                                       \
     328             :       BuildWithCodeStubAssemblerCS(isolate, index, &Builtins::Generate_##Name, \
     329             :                                    CallDescriptors::Name, #Name, 1);           \
     330             :   AddBuiltin(builtins, index++, code);
     331             : #define BUILD_TFH(Name, InterfaceDescriptor)               \
     332             :   /* Return size for IC builtins/handlers is always 1. */  \
     333             :   code = BuildWithCodeStubAssemblerCS(                     \
     334             :       isolate, index, &Builtins::Generate_##Name,          \
     335             :       CallDescriptors::InterfaceDescriptor, #Name, 1);     \
     336             :   AddBuiltin(builtins, index++, code);
     337             : 
     338             : #define BUILD_BCH(Name, OperandScale, Bytecode)                         \
     339             :   code = GenerateBytecodeHandler(isolate, index, Builtins::name(index), \
     340             :                                  OperandScale, Bytecode);               \
     341             :   AddBuiltin(builtins, index++, code);
     342             : 
     343             : #define BUILD_ASM(Name, InterfaceDescriptor)                                \
     344             :   code = BuildWithMacroAssembler(isolate, index, Builtins::Generate_##Name, \
     345             :                                  #Name);                                    \
     346             :   AddBuiltin(builtins, index++, code);
     347             : 
     348          56 :   BUILTIN_LIST(BUILD_CPP, BUILD_API, BUILD_TFJ, BUILD_TFC, BUILD_TFS, BUILD_TFH,
     349             :                BUILD_BCH, BUILD_ASM);
     350             : 
     351             : #undef BUILD_CPP
     352             : #undef BUILD_API
     353             : #undef BUILD_TFJ
     354             : #undef BUILD_TFC
     355             : #undef BUILD_TFS
     356             : #undef BUILD_TFH
     357             : #undef BUILD_BCH
     358             : #undef BUILD_ASM
     359          56 :   CHECK_EQ(Builtins::builtin_count, index);
     360             : 
     361          56 :   ReplacePlaceholders(isolate);
     362             : 
     363             : #define SET_PROMISE_REJECTION_PREDICTION(Name) \
     364             :   builtins->builtin(Builtins::k##Name)->set_is_promise_rejection(true);
     365             : 
     366          56 :   BUILTIN_PROMISE_REJECTION_PREDICTION_LIST(SET_PROMISE_REJECTION_PREDICTION)
     367             : #undef SET_PROMISE_REJECTION_PREDICTION
     368             : 
     369             : #define SET_EXCEPTION_CAUGHT_PREDICTION(Name) \
     370             :   builtins->builtin(Builtins::k##Name)->set_is_exception_caught(true);
     371             : 
     372          56 :   BUILTIN_EXCEPTION_CAUGHT_PREDICTION_LIST(SET_EXCEPTION_CAUGHT_PREDICTION)
     373             : #undef SET_EXCEPTION_CAUGHT_PREDICTION
     374             : 
     375          56 :   builtins->MarkInitialized();
     376          56 : }
     377             : 
     378             : }  // namespace internal
     379       86739 : }  // namespace v8

Generated by: LCOV version 1.10