LCOV - code coverage report
Current view: top level - src/builtins - builtins.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 51 74 68.9 %
Date: 2017-10-20 Functions: 19 23 82.6 %

          Line data    Source code
       1             : // Copyright 2012 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/builtins/builtins.h"
       6             : #include "src/api.h"
       7             : #include "src/assembler-inl.h"
       8             : #include "src/builtins/builtins-descriptors.h"
       9             : #include "src/callable.h"
      10             : #include "src/isolate.h"
      11             : #include "src/macro-assembler.h"
      12             : #include "src/objects-inl.h"
      13             : #include "src/visitors.h"
      14             : 
      15             : namespace v8 {
      16             : namespace internal {
      17             : 
      18             : // Forward declarations for C++ builtins.
      19             : #define FORWARD_DECLARE(Name) \
      20             :   Object* Builtin_##Name(int argc, Object** args, Isolate* isolate);
      21             : BUILTIN_LIST_C(FORWARD_DECLARE)
      22             : #undef FORWARD_DECLARE
      23             : 
      24             : namespace {
      25             : 
      26             : // TODO(jgruber): Pack in CallDescriptors::Key.
      27             : struct BuiltinMetadata {
      28             :   const char* name;
      29             :   Builtins::Kind kind;
      30             :   union {
      31             :     Address cpp_entry;       // For CPP and API builtins.
      32             :     int8_t parameter_count;  // For TFJ builtins.
      33             :   } kind_specific_data;
      34             : };
      35             : 
      36             : // clang-format off
      37             : #define DECL_CPP(Name, ...) { #Name, Builtins::CPP, \
      38             :                               { FUNCTION_ADDR(Builtin_##Name) }},
      39             : #define DECL_API(Name, ...) { #Name, Builtins::API, \
      40             :                               { FUNCTION_ADDR(Builtin_##Name) }},
      41             : #ifdef V8_TARGET_BIG_ENDIAN
      42             : #define DECL_TFJ(Name, Count, ...) { #Name, Builtins::TFJ, \
      43             :   { reinterpret_cast<Address>(static_cast<uintptr_t>(      \
      44             :                               Count) << (kBitsPerByte * (kPointerSize - 1))) }},
      45             : #else
      46             : #define DECL_TFJ(Name, Count, ...) { #Name, Builtins::TFJ, \
      47             :                               { reinterpret_cast<Address>(Count) }},
      48             : #endif
      49             : #define DECL_TFC(Name, ...) { #Name, Builtins::TFC, {} },
      50             : #define DECL_TFS(Name, ...) { #Name, Builtins::TFS, {} },
      51             : #define DECL_TFH(Name, ...) { #Name, Builtins::TFH, {} },
      52             : #define DECL_ASM(Name, ...) { #Name, Builtins::ASM, {} },
      53             : const BuiltinMetadata builtin_metadata[] = {
      54             :   BUILTIN_LIST(DECL_CPP, DECL_API, DECL_TFJ, DECL_TFC, DECL_TFS, DECL_TFH,
      55             :                DECL_ASM)
      56             : };
      57             : #undef DECL_CPP
      58             : #undef DECL_API
      59             : #undef DECL_TFJ
      60             : #undef DECL_TFC
      61             : #undef DECL_TFS
      62             : #undef DECL_TFH
      63             : #undef DECL_ASM
      64             : // clang-format on
      65             : 
      66             : }  // namespace
      67             : 
      68       54999 : Builtins::Builtins() : initialized_(false) {
      69       54999 :   memset(builtins_, 0, sizeof(builtins_[0]) * builtin_count);
      70       54999 : }
      71             : 
      72       53365 : Builtins::~Builtins() {}
      73             : 
      74        2935 : BailoutId Builtins::GetContinuationBailoutId(Name name) {
      75             :   DCHECK(Builtins::KindOf(name) == TFJ || Builtins::KindOf(name) == TFC);
      76        2935 :   return BailoutId(BailoutId::kFirstBuiltinContinuationId + name);
      77             : }
      78             : 
      79         892 : Builtins::Name Builtins::GetBuiltinFromBailoutId(BailoutId id) {
      80         892 :   int builtin_index = id.ToInt() - BailoutId::kFirstBuiltinContinuationId;
      81             :   DCHECK(Builtins::KindOf(builtin_index) == TFJ ||
      82             :          Builtins::KindOf(builtin_index) == TFC);
      83         892 :   return static_cast<Name>(builtin_index);
      84             : }
      85             : 
      86       53365 : void Builtins::TearDown() { initialized_ = false; }
      87             : 
      88      202771 : void Builtins::IterateBuiltins(RootVisitor* v) {
      89             :   v->VisitRootPointers(Root::kBuiltins, &builtins_[0],
      90      202771 :                        &builtins_[0] + builtin_count);
      91      202771 : }
      92             : 
      93           0 : const char* Builtins::Lookup(byte* pc) {
      94             :   // may be called during initialization (disassembler!)
      95           0 :   if (initialized_) {
      96           0 :     for (int i = 0; i < builtin_count; i++) {
      97           0 :       Code* entry = Code::cast(builtins_[i]);
      98           0 :       if (entry->contains(pc)) return name(i);
      99             :     }
     100             :   }
     101             :   return nullptr;
     102             : }
     103             : 
     104        5491 : Handle<Code> Builtins::NewFunctionContext(ScopeType scope_type) {
     105        5491 :   switch (scope_type) {
     106             :     case ScopeType::EVAL_SCOPE:
     107             :       return builtin_handle(kFastNewFunctionContextEval);
     108             :     case ScopeType::FUNCTION_SCOPE:
     109             :       return builtin_handle(kFastNewFunctionContextFunction);
     110             :     default:
     111           0 :       UNREACHABLE();
     112             :   }
     113             :   return Handle<Code>::null();
     114             : }
     115             : 
     116        1990 : Handle<Code> Builtins::NonPrimitiveToPrimitive(ToPrimitiveHint hint) {
     117        1990 :   switch (hint) {
     118             :     case ToPrimitiveHint::kDefault:
     119             :       return builtin_handle(kNonPrimitiveToPrimitive_Default);
     120             :     case ToPrimitiveHint::kNumber:
     121             :       return builtin_handle(kNonPrimitiveToPrimitive_Number);
     122             :     case ToPrimitiveHint::kString:
     123             :       return builtin_handle(kNonPrimitiveToPrimitive_String);
     124             :   }
     125           0 :   UNREACHABLE();
     126             : }
     127             : 
     128         155 : Handle<Code> Builtins::OrdinaryToPrimitive(OrdinaryToPrimitiveHint hint) {
     129         155 :   switch (hint) {
     130             :     case OrdinaryToPrimitiveHint::kNumber:
     131             :       return builtin_handle(kOrdinaryToPrimitive_Number);
     132             :     case OrdinaryToPrimitiveHint::kString:
     133             :       return builtin_handle(kOrdinaryToPrimitive_String);
     134             :   }
     135           0 :   UNREACHABLE();
     136             : }
     137             : 
     138    63573869 : void Builtins::set_builtin(int index, HeapObject* builtin) {
     139             :   DCHECK(Builtins::IsBuiltinId(index));
     140             :   DCHECK(Internals::HasHeapObjectTag(builtin));
     141             :   // The given builtin may be completely uninitialized thus we cannot check its
     142             :   // type here.
     143    63573869 :   builtins_[index] = builtin;
     144    63573869 : }
     145             : 
     146    18481939 : Handle<Code> Builtins::builtin_handle(int index) {
     147             :   DCHECK(IsBuiltinId(index));
     148    18520627 :   return Handle<Code>(reinterpret_cast<Code**>(builtin_address(index)));
     149             : }
     150             : 
     151             : // static
     152           0 : int Builtins::GetStackParameterCount(Name name) {
     153             :   DCHECK(Builtins::KindOf(name) == TFJ);
     154           0 :   return builtin_metadata[name].kind_specific_data.parameter_count;
     155             : }
     156             : 
     157             : // static
     158     2109831 : Callable Builtins::CallableFor(Isolate* isolate, Name name) {
     159             :   Handle<Code> code(
     160     2109831 :       reinterpret_cast<Code**>(isolate->builtins()->builtin_address(name)));
     161             :   CallDescriptors::Key key;
     162     2109831 :   switch (name) {
     163             : // This macro is deliberately crafted so as to emit very little code,
     164             : // in order to keep binary size of this function under control.
     165             : #define CASE_OTHER(Name, ...)                          \
     166             :   case k##Name: {                                      \
     167             :     key = Builtin_##Name##_InterfaceDescriptor::key(); \
     168             :     break;                                             \
     169             :   }
     170           0 :     BUILTIN_LIST(IGNORE_BUILTIN, IGNORE_BUILTIN, IGNORE_BUILTIN, CASE_OTHER,
     171             :                  CASE_OTHER, CASE_OTHER, IGNORE_BUILTIN)
     172             : #undef CASE_OTHER
     173             :     case kConsoleAssert: {
     174          62 :       return Callable(code, BuiltinDescriptor(isolate));
     175             :     }
     176             :     case kArrayForEach: {
     177             :       Handle<Code> code = BUILTIN_CODE(isolate, ArrayForEach);
     178           0 :       return Callable(code, BuiltinDescriptor(isolate));
     179             :     }
     180             :     case kArrayForEachLoopEagerDeoptContinuation: {
     181             :       Handle<Code> code =
     182             :           BUILTIN_CODE(isolate, ArrayForEachLoopEagerDeoptContinuation);
     183         960 :       return Callable(code, BuiltinDescriptor(isolate));
     184             :     }
     185             :     case kArrayForEachLoopLazyDeoptContinuation: {
     186             :       Handle<Code> code =
     187             :           BUILTIN_CODE(isolate, ArrayForEachLoopLazyDeoptContinuation);
     188        2044 :       return Callable(code, BuiltinDescriptor(isolate));
     189             :     }
     190             :     case kArrayMapLoopEagerDeoptContinuation: {
     191             :       Handle<Code> code =
     192             :           BUILTIN_CODE(isolate, ArrayMapLoopEagerDeoptContinuation);
     193         692 :       return Callable(code, BuiltinDescriptor(isolate));
     194             :     }
     195             :     case kArrayMapLoopLazyDeoptContinuation: {
     196             :       Handle<Code> code =
     197             :           BUILTIN_CODE(isolate, ArrayMapLoopLazyDeoptContinuation);
     198        1468 :       return Callable(code, BuiltinDescriptor(isolate));
     199             :     }
     200             :     default:
     201           0 :       UNREACHABLE();
     202             :   }
     203             :   CallInterfaceDescriptor descriptor(isolate, key);
     204             :   return Callable(code, descriptor);
     205             : }
     206             : 
     207             : // static
     208      255095 : const char* Builtins::name(int index) {
     209             :   DCHECK(IsBuiltinId(index));
     210      255095 :   return builtin_metadata[index].name;
     211             : }
     212             : 
     213             : // static
     214        7920 : Address Builtins::CppEntryOf(int index) {
     215             :   DCHECK(Builtins::HasCppImplementation(index));
     216        7920 :   return builtin_metadata[index].kind_specific_data.cpp_entry;
     217             : }
     218             : 
     219             : // static
     220   366913850 : bool Builtins::IsLazy(int index) {
     221             :   DCHECK(IsBuiltinId(index));
     222             :   // There are a couple of reasons that builtins can require eager-loading,
     223             :   // i.e. deserialization at isolate creation instead of on-demand. For
     224             :   // instance:
     225             :   // * DeserializeLazy implements lazy loading.
     226             :   // * Immovability requirement. This can only conveniently be guaranteed at
     227             :   //   isolate creation (at runtime, we'd have to allocate in LO space).
     228             :   // * To avoid conflicts in SharedFunctionInfo::function_data (Illegal,
     229             :   //   HandleApiCall, interpreter entry trampolines).
     230             :   // * Frequent use makes lazy loading unnecessary (CompileLazy).
     231             :   // TODO(wasm): Remove wasm builtins once immovability is no longer required.
     232   366913850 :   switch (index) {
     233             :     case kAbort:  // Required by wasm.
     234             :     case kArrayForEachLoopEagerDeoptContinuation:  // https://crbug.com/v8/6786.
     235             :     case kArrayForEachLoopLazyDeoptContinuation:   // https://crbug.com/v8/6786.
     236             :     case kArrayMapLoopEagerDeoptContinuation:      // https://crbug.com/v8/6786.
     237             :     case kArrayMapLoopLazyDeoptContinuation:       // https://crbug.com/v8/6786.
     238             :     case kCheckOptimizationMarker:
     239             :     case kCompileLazy:
     240             :     case kDeserializeLazy:
     241             :     case kFunctionPrototypeHasInstance:  // https://crbug.com/v8/6786.
     242             :     case kHandleApiCall:
     243             :     case kIllegal:
     244             :     case kInterpreterEnterBytecodeAdvance:
     245             :     case kInterpreterEnterBytecodeDispatch:
     246             :     case kInterpreterEntryTrampoline:
     247             :     case kObjectConstructor_ConstructStub:    // https://crbug.com/v8/6787.
     248             :     case kProxyConstructor_ConstructStub:     // https://crbug.com/v8/6787.
     249             :     case kNumberConstructor_ConstructStub:    // https://crbug.com/v8/6787.
     250             :     case kStringConstructor_ConstructStub:    // https://crbug.com/v8/6787.
     251             :     case kProxyConstructor:                   // https://crbug.com/v8/6787.
     252             :     case kRecordWrite:  // https://crbug.com/chromium/765301.
     253             :     case kThrowWasmTrapDivByZero:             // Required by wasm.
     254             :     case kThrowWasmTrapDivUnrepresentable:    // Required by wasm.
     255             :     case kThrowWasmTrapFloatUnrepresentable:  // Required by wasm.
     256             :     case kThrowWasmTrapFuncInvalid:           // Required by wasm.
     257             :     case kThrowWasmTrapFuncSigMismatch:       // Required by wasm.
     258             :     case kThrowWasmTrapMemOutOfBounds:        // Required by wasm.
     259             :     case kThrowWasmTrapRemByZero:             // Required by wasm.
     260             :     case kThrowWasmTrapUnreachable:           // Required by wasm.
     261             :     case kToNumber:                           // Required by wasm.
     262             :     case kWasmCompileLazy:                    // Required by wasm.
     263             :     case kWasmStackGuard:                     // Required by wasm.
     264             :       return false;
     265             :     default:
     266             :       // TODO(6624): Extend to other kinds.
     267   280613472 :       return KindOf(index) == TFJ;
     268             :   }
     269             :   UNREACHABLE();
     270             : }
     271             : 
     272             : // static
     273           0 : Builtins::Kind Builtins::KindOf(int index) {
     274             :   DCHECK(IsBuiltinId(index));
     275   280781359 :   return builtin_metadata[index].kind;
     276             : }
     277             : 
     278             : // static
     279           0 : const char* Builtins::KindNameOf(int index) {
     280             :   Kind kind = Builtins::KindOf(index);
     281             :   // clang-format off
     282           0 :   switch (kind) {
     283             :     case CPP: return "CPP";
     284           0 :     case API: return "API";
     285           0 :     case TFJ: return "TFJ";
     286           0 :     case TFC: return "TFC";
     287           0 :     case TFS: return "TFS";
     288           0 :     case TFH: return "TFH";
     289           0 :     case ASM: return "ASM";
     290             :   }
     291             :   // clang-format on
     292           0 :   UNREACHABLE();
     293             : }
     294             : 
     295             : // static
     296       15680 : bool Builtins::IsCpp(int index) { return Builtins::KindOf(index) == CPP; }
     297             : 
     298             : // static
     299      160047 : bool Builtins::HasCppImplementation(int index) {
     300             :   Kind kind = Builtins::KindOf(index);
     301      160047 :   return (kind == CPP || kind == API);
     302             : }
     303             : 
     304     7858314 : Handle<Code> Builtins::JSConstructStubGeneric() {
     305             :   return FLAG_harmony_restrict_constructor_return
     306             :              ? builtin_handle(kJSConstructStubGenericRestrictedReturn)
     307    15716628 :              : builtin_handle(kJSConstructStubGenericUnrestrictedReturn);
     308             : }
     309             : 
     310             : // static
     311     2397150 : bool Builtins::AllowDynamicFunction(Isolate* isolate, Handle<JSFunction> target,
     312             :                                     Handle<JSObject> target_global_proxy) {
     313     1198683 :   if (FLAG_allow_unsafe_function_constructor) return true;
     314             :   HandleScopeImplementer* impl = isolate->handle_scope_implementer();
     315             :   Handle<Context> responsible_context =
     316             :       impl->MicrotaskContextIsLastEnteredContext() ? impl->MicrotaskContext()
     317     1198467 :                                                    : impl->LastEnteredContext();
     318             :   // TODO(jochen): Remove this.
     319     1198467 :   if (responsible_context.is_null()) {
     320             :     return true;
     321             :   }
     322     1198467 :   if (*responsible_context == target->context()) return true;
     323         285 :   return isolate->MayAccess(responsible_context, target_global_proxy);
     324             : }
     325             : 
     326             : }  // namespace internal
     327             : }  // namespace v8

Generated by: LCOV version 1.10