LCOV - code coverage report
Current view: top level - src/builtins - setup-builtins-internal.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 132 139 95.0 %
Date: 2019-03-21 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       84840 : void PostBuildProfileAndTracing(Isolate* isolate, Code code, const char* name) {
      35       84840 :   PROFILE(isolate, CodeCreateEvent(CodeEventListener::BUILTIN_TAG,
      36             :                                    AbstractCode::cast(code), name));
      37       84840 : }
      38             : 
      39       84840 : AssemblerOptions BuiltinAssemblerOptions(Isolate* isolate,
      40             :                                          int32_t builtin_index) {
      41       84840 :   AssemblerOptions options = AssemblerOptions::Default(isolate);
      42       84840 :   CHECK(!options.isolate_independent_code);
      43       84840 :   CHECK(!options.use_pc_relative_calls_and_jumps);
      44             : 
      45      169680 :   if (!isolate->IsGeneratingEmbeddedBuiltins() ||
      46       84840 :       !Builtins::IsIsolateIndependent(builtin_index)) {
      47           0 :     return options;
      48             :   }
      49             : 
      50             :   const base::AddressRegion& code_range =
      51       84840 :       isolate->heap()->memory_allocator()->code_range();
      52             :   bool pc_relative_calls_fit_in_code_range =
      53      169680 :       !code_range.is_empty() &&
      54       84840 :       std::ceil(static_cast<float>(code_range.size() / MB)) <=
      55       84840 :           kMaxPCRelativeCodeRangeInMB;
      56             : 
      57       84840 :   options.isolate_independent_code = true;
      58       84840 :   options.use_pc_relative_calls_and_jumps = pc_relative_calls_fit_in_code_range;
      59             : 
      60       84840 :   return options;
      61             : }
      62             : 
      63             : typedef void (*MacroAssemblerGenerator)(MacroAssembler*);
      64             : typedef void (*CodeAssemblerGenerator)(compiler::CodeAssemblerState*);
      65             : 
      66       84840 : Handle<Code> BuildPlaceholder(Isolate* isolate, int32_t builtin_index) {
      67      169680 :   HandleScope scope(isolate);
      68       84840 :   constexpr int kBufferSize = 1 * KB;
      69             :   byte buffer[kBufferSize];
      70             :   MacroAssembler masm(isolate, CodeObjectRequired::kYes,
      71      169680 :                       ExternalAssemblerBuffer(buffer, kBufferSize));
      72             :   DCHECK(!masm.has_frame());
      73             :   {
      74      169680 :     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       84840 :     masm.Move(kJavaScriptCallCodeStartRegister, Smi::zero());
      78       84840 :     masm.Call(kJavaScriptCallCodeStartRegister);
      79             :   }
      80       84840 :   CodeDesc desc;
      81       84840 :   masm.GetCode(isolate, &desc);
      82             :   Handle<Code> code = isolate->factory()->NewCode(
      83      339360 :       desc, Code::BUILTIN, masm.CodeObject(), builtin_index);
      84      169680 :   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        7840 :   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        7840 :   MacroAssembler masm(isolate, BuiltinAssemblerOptions(isolate, builtin_index),
      98             :                       CodeObjectRequired::kYes,
      99       15680 :                       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         168 :     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       30912 :   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       30912 :   MacroAssembler masm(isolate, BuiltinAssemblerOptions(isolate, builtin_index),
     143             :                       CodeObjectRequired::kYes,
     144       61824 :                       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       38080 :   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       19880 : Code BuildWithCodeStubAssemblerCS(Isolate* isolate, int32_t builtin_index,
     183             :                                   CodeAssemblerGenerator generator,
     184             :                                   CallDescriptors::Key interface_descriptor,
     185             :                                   const char* name) {
     186       39760 :   HandleScope scope(isolate);
     187             :   // Canonicalize handles, so that we can share constant pool entries pointing
     188             :   // to code targets without dereferencing their handles.
     189       39760 :   CanonicalHandleScope canonical(isolate);
     190       19880 :   SegmentSize segment_size = isolate->serializer_enabled()
     191             :                                  ? SegmentSize::kLarge
     192       19880 :                                  : SegmentSize::kDefault;
     193       39760 :   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       39760 :   CallInterfaceDescriptor descriptor(interface_descriptor);
     197             :   // Ensure descriptor is already initialized.
     198             :   DCHECK_LE(0, descriptor.GetRegisterParameterCount());
     199             :   compiler::CodeAssemblerState state(
     200             :       isolate, &zone, descriptor, Code::BUILTIN, name,
     201       39760 :       PoisoningMitigationLevel::kDontPoison, builtin_index);
     202       19880 :   generator(&state);
     203             :   Handle<Code> code = compiler::CodeAssembler::GenerateCode(
     204       19880 :       &state, BuiltinAssemblerOptions(isolate, builtin_index));
     205       19880 :   PostBuildProfileAndTracing(isolate, *code, name);
     206       19880 :   return *code;
     207             : }
     208             : 
     209             : }  // anonymous namespace
     210             : 
     211             : // static
     212      169680 : void SetupIsolateDelegate::AddBuiltin(Builtins* builtins, int index,
     213             :                                       Code code) {
     214             :   DCHECK_EQ(index, code->builtin_index());
     215      169680 :   builtins->set_builtin(index, code);
     216      169680 : }
     217             : 
     218             : // static
     219          56 : void SetupIsolateDelegate::PopulateWithPlaceholders(Isolate* isolate) {
     220             :   // Fill the builtins list with placeholders. References to these placeholder
     221             :   // builtins are eventually replaced by the actual builtins. This is to
     222             :   // support circular references between builtins.
     223          56 :   Builtins* builtins = isolate->builtins();
     224         112 :   HandleScope scope(isolate);
     225       84896 :   for (int i = 0; i < Builtins::builtin_count; i++) {
     226       84840 :     Handle<Code> placeholder = BuildPlaceholder(isolate, i);
     227       84840 :     AddBuiltin(builtins, i, *placeholder);
     228             :   }
     229          56 : }
     230             : 
     231             : // static
     232          56 : void SetupIsolateDelegate::ReplacePlaceholders(Isolate* isolate) {
     233             :   // Replace references from all code objects to placeholders.
     234          56 :   Builtins* builtins = isolate->builtins();
     235          56 :   DisallowHeapAllocation no_gc;
     236         112 :   CodeSpaceMemoryModificationScope modification_scope(isolate->heap());
     237             :   static const int kRelocMask =
     238             :       RelocInfo::ModeMask(RelocInfo::CODE_TARGET) |
     239             :       RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT) |
     240             :       RelocInfo::ModeMask(RelocInfo::RELATIVE_CODE_TARGET);
     241         112 :   HeapIterator iterator(isolate->heap());
     242      571648 :   for (HeapObject obj = iterator.next(); !obj.is_null();
     243             :        obj = iterator.next()) {
     244     1143184 :     if (!obj->IsCode()) continue;
     245      169680 :     Code code = Code::cast(obj);
     246      169680 :     bool flush_icache = false;
     247      572096 :     for (RelocIterator it(code, kRelocMask); !it.done(); it.next()) {
     248      402416 :       RelocInfo* rinfo = it.rinfo();
     249      402416 :       if (RelocInfo::IsCodeTargetMode(rinfo->rmode())) {
     250      402416 :         Code target = Code::GetCodeFromTargetAddress(rinfo->target_address());
     251             :         DCHECK_IMPLIES(RelocInfo::IsRelativeCodeTarget(rinfo->rmode()),
     252             :                        Builtins::IsIsolateIndependent(target->builtin_index()));
     253      402416 :         if (!target->is_builtin()) continue;
     254      402416 :         Code new_target = builtins->builtin(target->builtin_index());
     255      402416 :         rinfo->set_target_address(new_target->raw_instruction_start(),
     256      402416 :                                   UPDATE_WRITE_BARRIER, SKIP_ICACHE_FLUSH);
     257             :       } else {
     258             :         DCHECK(RelocInfo::IsEmbeddedObject(rinfo->rmode()));
     259           0 :         Object object = rinfo->target_object();
     260           0 :         if (!object->IsCode()) continue;
     261           0 :         Code target = Code::cast(object);
     262           0 :         if (!target->is_builtin()) continue;
     263           0 :         Code new_target = builtins->builtin(target->builtin_index());
     264           0 :         rinfo->set_target_object(isolate->heap(), new_target,
     265             :                                  UPDATE_WRITE_BARRIER, SKIP_ICACHE_FLUSH);
     266             :       }
     267      402416 :       flush_icache = true;
     268             :     }
     269      169680 :     if (flush_icache) {
     270       73248 :       FlushInstructionCache(code->raw_instruction_start(),
     271       73248 :                             code->raw_instruction_size());
     272             :     }
     273             :   }
     274          56 : }
     275             : 
     276             : namespace {
     277             : 
     278       26544 : Code GenerateBytecodeHandler(Isolate* isolate, int builtin_index,
     279             :                              const char* name,
     280             :                              interpreter::OperandScale operand_scale,
     281             :                              interpreter::Bytecode bytecode) {
     282             :   DCHECK(interpreter::Bytecodes::BytecodeHasHandler(bytecode, operand_scale));
     283             : 
     284             :   Handle<Code> code = interpreter::GenerateBytecodeHandler(
     285             :       isolate, bytecode, operand_scale, builtin_index,
     286       26544 :       BuiltinAssemblerOptions(isolate, builtin_index));
     287             : 
     288       26544 :   PostBuildProfileAndTracing(isolate, *code, name);
     289             : 
     290       26544 :   return *code;
     291             : }
     292             : 
     293             : }  // namespace
     294             : 
     295             : // static
     296          56 : void SetupIsolateDelegate::SetupBuiltinsInternal(Isolate* isolate) {
     297          56 :   Builtins* builtins = isolate->builtins();
     298             :   DCHECK(!builtins->initialized_);
     299             : 
     300          56 :   PopulateWithPlaceholders(isolate);
     301             : 
     302             :   // Create a scope for the handles in the builtins.
     303         112 :   HandleScope scope(isolate);
     304             : 
     305          56 :   int index = 0;
     306          56 :   Code code;
     307             : #define BUILD_CPP(Name)                                              \
     308             :   code = BuildAdaptor(isolate, index, FUNCTION_ADDR(Builtin_##Name), \
     309             :                       Builtins::BUILTIN_EXIT, #Name);                \
     310             :   AddBuiltin(builtins, index++, code);
     311             : #define BUILD_API(Name)                                              \
     312             :   code = BuildAdaptor(isolate, index, FUNCTION_ADDR(Builtin_##Name), \
     313             :                       Builtins::EXIT, #Name);                        \
     314             :   AddBuiltin(builtins, index++, code);
     315             : #define BUILD_TFJ(Name, Argc, ...)                              \
     316             :   code = BuildWithCodeStubAssemblerJS(                          \
     317             :       isolate, index, &Builtins::Generate_##Name, Argc, #Name); \
     318             :   AddBuiltin(builtins, index++, code);
     319             : #define BUILD_TFC(Name, InterfaceDescriptor)                      \
     320             :   /* Return size is from the provided CallInterfaceDescriptor. */ \
     321             :   code = BuildWithCodeStubAssemblerCS(                            \
     322             :       isolate, index, &Builtins::Generate_##Name,                 \
     323             :       CallDescriptors::InterfaceDescriptor, #Name);               \
     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);              \
     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);       \
     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       87414 : }  // namespace v8

Generated by: LCOV version 1.10