LCOV - code coverage report
Current view: top level - src/asmjs - asm-js.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 136 146 93.2 %
Date: 2019-04-17 Functions: 15 16 93.8 %

          Line data    Source code
       1             : // Copyright 2015 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/asmjs/asm-js.h"
       6             : 
       7             : #include "src/asmjs/asm-names.h"
       8             : #include "src/asmjs/asm-parser.h"
       9             : #include "src/assert-scope.h"
      10             : #include "src/ast/ast.h"
      11             : #include "src/base/optional.h"
      12             : #include "src/base/platform/elapsed-timer.h"
      13             : #include "src/compiler.h"
      14             : #include "src/counters.h"
      15             : #include "src/execution.h"
      16             : #include "src/handles.h"
      17             : #include "src/heap/factory.h"
      18             : #include "src/isolate.h"
      19             : #include "src/message-template.h"
      20             : #include "src/objects-inl.h"
      21             : #include "src/objects/heap-number-inl.h"
      22             : #include "src/parsing/parse-info.h"
      23             : #include "src/parsing/scanner-character-streams.h"
      24             : #include "src/parsing/scanner.h"
      25             : #include "src/unoptimized-compilation-info.h"
      26             : #include "src/vector.h"
      27             : 
      28             : #include "src/wasm/wasm-engine.h"
      29             : #include "src/wasm/wasm-js.h"
      30             : #include "src/wasm/wasm-limits.h"
      31             : #include "src/wasm/wasm-module-builder.h"
      32             : #include "src/wasm/wasm-objects-inl.h"
      33             : #include "src/wasm/wasm-result.h"
      34             : 
      35             : namespace v8 {
      36             : namespace internal {
      37             : 
      38             : const char* const AsmJs::kSingleFunctionName = "__single_function__";
      39             : 
      40             : namespace {
      41             : 
      42        4861 : Handle<Object> StdlibMathMember(Isolate* isolate, Handle<JSReceiver> stdlib,
      43             :                                 Handle<Name> name) {
      44             :   Handle<Name> math_name(
      45        4861 :       isolate->factory()->InternalizeOneByteString(StaticCharVector("Math")));
      46        4861 :   Handle<Object> math = JSReceiver::GetDataProperty(stdlib, math_name);
      47        4865 :   if (!math->IsJSReceiver()) return isolate->factory()->undefined_value();
      48        4857 :   Handle<JSReceiver> math_receiver = Handle<JSReceiver>::cast(math);
      49        4857 :   Handle<Object> value = JSReceiver::GetDataProperty(math_receiver, name);
      50        4857 :   return value;
      51             : }
      52             : 
      53        2151 : bool AreStdlibMembersValid(Isolate* isolate, Handle<JSReceiver> stdlib,
      54             :                            wasm::AsmJsParser::StdlibSet members,
      55             :                            bool* is_typed_array) {
      56        2151 :   if (members.contains(wasm::AsmJsParser::StandardMember::kInfinity)) {
      57             :     members.Remove(wasm::AsmJsParser::StandardMember::kInfinity);
      58             :     Handle<Name> name = isolate->factory()->Infinity_string();
      59           8 :     Handle<Object> value = JSReceiver::GetDataProperty(stdlib, name);
      60          16 :     if (!value->IsNumber() || !std::isinf(value->Number())) return false;
      61             :   }
      62        2151 :   if (members.contains(wasm::AsmJsParser::StandardMember::kNaN)) {
      63             :     members.Remove(wasm::AsmJsParser::StandardMember::kNaN);
      64             :     Handle<Name> name = isolate->factory()->NaN_string();
      65          16 :     Handle<Object> value = JSReceiver::GetDataProperty(stdlib, name);
      66          16 :     if (!value->IsNaN()) return false;
      67             :   }
      68             : #define STDLIB_MATH_FUNC(fname, FName, ignore1, ignore2)                   \
      69             :   if (members.contains(wasm::AsmJsParser::StandardMember::kMath##FName)) { \
      70             :     members.Remove(wasm::AsmJsParser::StandardMember::kMath##FName);       \
      71             :     Handle<Name> name(isolate->factory()->InternalizeOneByteString(        \
      72             :         StaticCharVector(#fname)));                                        \
      73             :     Handle<Object> value = StdlibMathMember(isolate, stdlib, name);        \
      74             :     if (!value->IsJSFunction()) return false;                              \
      75             :     SharedFunctionInfo shared = Handle<JSFunction>::cast(value)->shared(); \
      76             :     if (!shared->HasBuiltinId() ||                                         \
      77             :         shared->builtin_id() != Builtins::kMath##FName) {                  \
      78             :       return false;                                                        \
      79             :     }                                                                      \
      80             :     DCHECK_EQ(shared->GetCode(),                                           \
      81             :               isolate->builtins()->builtin(Builtins::kMath##FName));       \
      82             :   }
      83       59993 :   STDLIB_MATH_FUNCTION_LIST(STDLIB_MATH_FUNC)
      84             : #undef STDLIB_MATH_FUNC
      85             : #define STDLIB_MATH_CONST(cname, const_value)                               \
      86             :   if (members.contains(wasm::AsmJsParser::StandardMember::kMath##cname)) {  \
      87             :     members.Remove(wasm::AsmJsParser::StandardMember::kMath##cname);        \
      88             :     Handle<Name> name(isolate->factory()->InternalizeOneByteString(         \
      89             :         StaticCharVector(#cname)));                                         \
      90             :     Handle<Object> value = StdlibMathMember(isolate, stdlib, name);         \
      91             :     if (!value->IsNumber() || value->Number() != const_value) return false; \
      92             :   }
      93       17508 :   STDLIB_MATH_VALUE_LIST(STDLIB_MATH_CONST)
      94             : #undef STDLIB_MATH_CONST
      95             : #define STDLIB_ARRAY_TYPE(fname, FName)                                \
      96             :   if (members.contains(wasm::AsmJsParser::StandardMember::k##FName)) { \
      97             :     members.Remove(wasm::AsmJsParser::StandardMember::k##FName);       \
      98             :     *is_typed_array = true;                                            \
      99             :     Handle<Name> name(isolate->factory()->InternalizeOneByteString(    \
     100             :         StaticCharVector(#FName)));                                    \
     101             :     Handle<Object> value = JSReceiver::GetDataProperty(stdlib, name);  \
     102             :     if (!value->IsJSFunction()) return false;                          \
     103             :     Handle<JSFunction> func = Handle<JSFunction>::cast(value);         \
     104             :     if (!func.is_identical_to(isolate->fname())) return false;         \
     105             :   }
     106        2675 :   STDLIB_ARRAY_TYPE(int8_array_fun, Int8Array)
     107        2907 :   STDLIB_ARRAY_TYPE(uint8_array_fun, Uint8Array)
     108        2627 :   STDLIB_ARRAY_TYPE(int16_array_fun, Int16Array)
     109        2531 :   STDLIB_ARRAY_TYPE(uint16_array_fun, Uint16Array)
     110        6115 :   STDLIB_ARRAY_TYPE(int32_array_fun, Int32Array)
     111        2643 :   STDLIB_ARRAY_TYPE(uint32_array_fun, Uint32Array)
     112        2755 :   STDLIB_ARRAY_TYPE(float32_array_fun, Float32Array)
     113        2565 :   STDLIB_ARRAY_TYPE(float64_array_fun, Float64Array)
     114             : #undef STDLIB_ARRAY_TYPE
     115             :   // All members accounted for.
     116             :   DCHECK(members.empty());
     117             :   return true;
     118             : }
     119             : 
     120         171 : void Report(Handle<Script> script, int position, Vector<const char> text,
     121             :             MessageTemplate message_template,
     122             :             v8::Isolate::MessageErrorLevel level) {
     123             :   Isolate* isolate = script->GetIsolate();
     124         171 :   MessageLocation location(script, position, position);
     125         171 :   Handle<String> text_object = isolate->factory()->InternalizeUtf8String(text);
     126             :   Handle<JSMessageObject> message = MessageHandler::MakeMessageObject(
     127             :       isolate, message_template, &location, text_object,
     128         171 :       Handle<FixedArray>::null());
     129         171 :   message->set_error_level(level);
     130         171 :   MessageHandler::ReportMessage(isolate, &location, message);
     131         171 : }
     132             : 
     133             : // Hook to report successful execution of {AsmJs::CompileAsmViaWasm} phase.
     134        2469 : void ReportCompilationSuccess(Handle<Script> script, int position,
     135             :                               double translate_time, double compile_time,
     136             :                               size_t module_size) {
     137        4938 :   if (FLAG_suppress_asm_messages || !FLAG_trace_asm_time) return;
     138             :   EmbeddedVector<char, 100> text;
     139             :   int length = SNPrintF(
     140             :       text, "success, asm->wasm: %0.3f ms, compile: %0.3f ms, %" PRIuS " bytes",
     141           0 :       translate_time, compile_time, module_size);
     142           0 :   CHECK_NE(-1, length);
     143           0 :   text.Truncate(length);
     144             :   Report(script, position, text, MessageTemplate::kAsmJsCompiled,
     145           0 :          v8::Isolate::kMessageInfo);
     146             : }
     147             : 
     148             : // Hook to report failed execution of {AsmJs::CompileAsmViaWasm} phase.
     149             : void ReportCompilationFailure(ParseInfo* parse_info, int position,
     150             :                               const char* reason) {
     151        1260 :   if (FLAG_suppress_asm_messages) return;
     152             :   parse_info->pending_error_handler()->ReportWarningAt(
     153        1260 :       position, position, MessageTemplate::kAsmJsInvalid, reason);
     154             : }
     155             : 
     156             : // Hook to report successful execution of {AsmJs::InstantiateAsmWasm} phase.
     157        4847 : void ReportInstantiationSuccess(Handle<Script> script, int position,
     158             :                                 double instantiate_time) {
     159        9694 :   if (FLAG_suppress_asm_messages || !FLAG_trace_asm_time) return;
     160             :   EmbeddedVector<char, 50> text;
     161           0 :   int length = SNPrintF(text, "success, %0.3f ms", instantiate_time);
     162           0 :   CHECK_NE(-1, length);
     163           0 :   text.Truncate(length);
     164             :   Report(script, position, text, MessageTemplate::kAsmJsInstantiated,
     165           0 :          v8::Isolate::kMessageInfo);
     166             : }
     167             : 
     168             : // Hook to report failed execution of {AsmJs::InstantiateAsmWasm} phase.
     169         171 : void ReportInstantiationFailure(Handle<Script> script, int position,
     170             :                                 const char* reason) {
     171         171 :   if (FLAG_suppress_asm_messages) return;
     172         171 :   Vector<const char> text = CStrVector(reason);
     173             :   Report(script, position, text, MessageTemplate::kAsmJsLinkingFailed,
     174         171 :          v8::Isolate::kMessageWarning);
     175             : }
     176             : 
     177             : }  // namespace
     178             : 
     179             : // The compilation of asm.js modules is split into two distinct steps:
     180             : //  [1] ExecuteJobImpl: The asm.js module source is parsed, validated, and
     181             : //      translated to a valid WebAssembly module. The result are two vectors
     182             : //      representing the encoded module as well as encoded source position
     183             : //      information and a StdlibSet bit set.
     184             : //  [2] FinalizeJobImpl: The module is handed to WebAssembly which decodes it
     185             : //      into an internal representation and eventually compiles it to machine
     186             : //      code.
     187       11277 : class AsmJsCompilationJob final : public UnoptimizedCompilationJob {
     188             :  public:
     189        3759 :   explicit AsmJsCompilationJob(ParseInfo* parse_info, FunctionLiteral* literal,
     190             :                                AccountingAllocator* allocator)
     191             :       : UnoptimizedCompilationJob(parse_info->stack_limit(), parse_info,
     192             :                                   &compilation_info_),
     193             :         allocator_(allocator),
     194             :         zone_(allocator, ZONE_NAME),
     195             :         compilation_info_(&zone_, parse_info, literal),
     196             :         module_(nullptr),
     197             :         asm_offsets_(nullptr),
     198             :         translate_time_(0),
     199             :         compile_time_(0),
     200             :         module_source_size_(0),
     201             :         translate_time_micro_(0),
     202       11277 :         translate_zone_size_(0) {}
     203             : 
     204             :  protected:
     205             :   Status ExecuteJobImpl() final;
     206             :   Status FinalizeJobImpl(Handle<SharedFunctionInfo> shared_info,
     207             :                          Isolate* isolate) final;
     208             : 
     209             :  private:
     210             :   void RecordHistograms(Isolate* isolate);
     211             : 
     212             :   AccountingAllocator* allocator_;
     213             :   Zone zone_;
     214             :   UnoptimizedCompilationInfo compilation_info_;
     215             :   wasm::ZoneBuffer* module_;
     216             :   wasm::ZoneBuffer* asm_offsets_;
     217             :   wasm::AsmJsParser::StdlibSet stdlib_uses_;
     218             : 
     219             :   double translate_time_;   // Time (milliseconds) taken to execute step [1].
     220             :   double compile_time_;     // Time (milliseconds) taken to execute step [2].
     221             :   int module_source_size_;  // Module source size in bytes.
     222             :   int64_t translate_time_micro_;  // Time (microseconds) taken to translate.
     223             :   size_t translate_zone_size_;
     224             : 
     225             :   DISALLOW_COPY_AND_ASSIGN(AsmJsCompilationJob);
     226             : };
     227             : 
     228        3759 : UnoptimizedCompilationJob::Status AsmJsCompilationJob::ExecuteJobImpl() {
     229             :   // Step 1: Translate asm.js module to WebAssembly module.
     230             :   size_t compile_zone_start = compilation_info()->zone()->allocation_size();
     231             :   base::ElapsedTimer translate_timer;
     232             :   translate_timer.Start();
     233             : 
     234             :   Zone* compile_zone = compilation_info()->zone();
     235        7518 :   Zone translate_zone(allocator_, ZONE_NAME);
     236             : 
     237             :   Utf16CharacterStream* stream = parse_info()->character_stream();
     238             :   base::Optional<AllowHandleDereference> allow_deref;
     239        3759 :   if (stream->can_access_heap()) {
     240             :     allow_deref.emplace();
     241             :   }
     242        3759 :   stream->Seek(compilation_info()->literal()->start_position());
     243        3759 :   wasm::AsmJsParser parser(&translate_zone, stack_limit(), stream);
     244        3759 :   if (!parser.Run()) {
     245        1260 :     if (!FLAG_suppress_asm_messages) {
     246             :       ReportCompilationFailure(parse_info(), parser.failure_location(),
     247             :                                parser.failure_message());
     248             :     }
     249             :     return FAILED;
     250             :   }
     251        2499 :   module_ = new (compile_zone) wasm::ZoneBuffer(compile_zone);
     252        2499 :   parser.module_builder()->WriteTo(*module_);
     253        2499 :   asm_offsets_ = new (compile_zone) wasm::ZoneBuffer(compile_zone);
     254        2499 :   parser.module_builder()->WriteAsmJsOffsetTable(*asm_offsets_);
     255        2499 :   stdlib_uses_ = *parser.stdlib_uses();
     256             : 
     257             :   size_t compile_zone_size =
     258        2499 :       compilation_info()->zone()->allocation_size() - compile_zone_start;
     259        2499 :   translate_zone_size_ = translate_zone.allocation_size();
     260        2499 :   translate_time_ = translate_timer.Elapsed().InMillisecondsF();
     261        2499 :   translate_time_micro_ = translate_timer.Elapsed().InMicroseconds();
     262        4998 :   module_source_size_ = compilation_info()->literal()->end_position() -
     263        4998 :                         compilation_info()->literal()->start_position();
     264        2499 :   if (FLAG_trace_asm_parser) {
     265           0 :     PrintF(
     266             :         "[asm.js translation successful: time=%0.3fms, "
     267             :         "translate_zone=%" PRIuS "KB, compile_zone+=%" PRIuS "KB]\n",
     268           0 :         translate_time_, translate_zone_size_ / KB, compile_zone_size / KB);
     269             :   }
     270             :   return SUCCEEDED;
     271             : }
     272             : 
     273        2469 : UnoptimizedCompilationJob::Status AsmJsCompilationJob::FinalizeJobImpl(
     274             :     Handle<SharedFunctionInfo> shared_info, Isolate* isolate) {
     275             :   // Step 2: Compile and decode the WebAssembly module.
     276             :   base::ElapsedTimer compile_timer;
     277             :   compile_timer.Start();
     278             : 
     279             :   Handle<HeapNumber> uses_bitset =
     280        2469 :       isolate->factory()->NewHeapNumberFromBits(stdlib_uses_.ToIntegral());
     281             : 
     282             :   // The result is a compiled module and serialized standard library uses.
     283        2469 :   wasm::ErrorThrower thrower(isolate, "AsmJs::Compile");
     284             :   Handle<AsmWasmData> result =
     285             :       isolate->wasm_engine()
     286        4938 :           ->SyncCompileTranslatedAsmJs(
     287             :               isolate, &thrower,
     288        2469 :               wasm::ModuleWireBytes(module_->begin(), module_->end()),
     289        2469 :               Vector<const byte>(asm_offsets_->begin(), asm_offsets_->size()),
     290        2469 :               uses_bitset)
     291             :           .ToHandleChecked();
     292             :   DCHECK(!thrower.error());
     293        2469 :   compile_time_ = compile_timer.Elapsed().InMillisecondsF();
     294             : 
     295             :   compilation_info()->SetAsmWasmData(result);
     296             : 
     297        2469 :   RecordHistograms(isolate);
     298        2469 :   ReportCompilationSuccess(parse_info()->script(),
     299             :                            compilation_info()->literal()->position(),
     300        4938 :                            translate_time_, compile_time_, module_->size());
     301        2469 :   return SUCCEEDED;
     302             : }
     303             : 
     304        2469 : void AsmJsCompilationJob::RecordHistograms(Isolate* isolate) {
     305             :   Counters* counters = isolate->counters();
     306        2469 :   counters->asm_wasm_translation_time()->AddSample(
     307        4938 :       static_cast<int>(translate_time_micro_));
     308        2469 :   counters->asm_wasm_translation_peak_memory_bytes()->AddSample(
     309        4938 :       static_cast<int>(translate_zone_size_));
     310        4938 :   counters->asm_module_size_bytes()->AddSample(module_source_size_);
     311             :   // translation_throughput is not exact (assumes MB == 1000000). But that is ok
     312             :   // since the metric is stored in buckets that lose some precision anyways.
     313             :   int translation_throughput =
     314        2469 :       translate_time_micro_ != 0
     315        2469 :           ? static_cast<int>(static_cast<int64_t>(module_source_size_) /
     316             :                              translate_time_micro_)
     317        4938 :           : 0;
     318             :   counters->asm_wasm_translation_throughput()->AddSample(
     319        2469 :       translation_throughput);
     320        2469 : }
     321             : 
     322        3759 : UnoptimizedCompilationJob* AsmJs::NewCompilationJob(
     323             :     ParseInfo* parse_info, FunctionLiteral* literal,
     324             :     AccountingAllocator* allocator) {
     325        3759 :   return new AsmJsCompilationJob(parse_info, literal, allocator);
     326             : }
     327             : 
     328             : namespace {
     329        1324 : inline bool IsValidAsmjsMemorySize(size_t size) {
     330             :   // Enforce asm.js spec minimum size.
     331        1324 :   if (size < (1u << 12u)) return false;
     332             :   // Enforce engine-limited and flag-limited maximum allocation size.
     333        1269 :   if (size > wasm::max_mem_pages() * uint64_t{wasm::kWasmPageSize}) {
     334             :     return false;
     335             :   }
     336             :   // Enforce power-of-2 sizes for 2^12 - 2^24.
     337        1261 :   if (size < (1u << 24u)) {
     338        1154 :     uint32_t size32 = static_cast<uint32_t>(size);
     339        1154 :     return base::bits::IsPowerOfTwo(size32);
     340             :   }
     341             :   // Enforce multiple of 2^24 for sizes >= 2^24
     342         107 :   if ((size % (1u << 24u)) != 0) return false;
     343             :   // All checks passed!
     344          98 :   return true;
     345             : }
     346             : }  // namespace
     347             : 
     348        5018 : MaybeHandle<Object> AsmJs::InstantiateAsmWasm(Isolate* isolate,
     349             :                                               Handle<SharedFunctionInfo> shared,
     350             :                                               Handle<AsmWasmData> wasm_data,
     351             :                                               Handle<JSReceiver> stdlib,
     352             :                                               Handle<JSReceiver> foreign,
     353             :                                               Handle<JSArrayBuffer> memory) {
     354             :   base::ElapsedTimer instantiate_timer;
     355             :   instantiate_timer.Start();
     356             :   Handle<HeapNumber> uses_bitset(wasm_data->uses_bitset(), isolate);
     357       10036 :   Handle<Script> script(Script::cast(shared->script()), isolate);
     358             :   const auto& wasm_engine = isolate->wasm_engine();
     359             : 
     360             :   // Allocate the WasmModuleObject.
     361             :   Handle<WasmModuleObject> module =
     362        5018 :       wasm_engine->FinalizeTranslatedAsmJs(isolate, wasm_data, script);
     363             : 
     364             :   // TODO(mstarzinger): The position currently points to the module definition
     365             :   // but should instead point to the instantiation site (more intuitive).
     366        5018 :   int position = shared->StartPosition();
     367             : 
     368             :   // Check that all used stdlib members are valid.
     369        5018 :   bool stdlib_use_of_typed_array_present = false;
     370             :   wasm::AsmJsParser::StdlibSet stdlib_uses =
     371             :       wasm::AsmJsParser::StdlibSet::FromIntegral(uses_bitset->value_as_bits());
     372        5018 :   if (!stdlib_uses.empty()) {  // No checking needed if no uses.
     373        2167 :     if (stdlib.is_null()) {
     374          16 :       ReportInstantiationFailure(script, position, "Requires standard library");
     375          16 :       return MaybeHandle<Object>();
     376             :     }
     377        2151 :     if (!AreStdlibMembersValid(isolate, stdlib, stdlib_uses,
     378             :                                &stdlib_use_of_typed_array_present)) {
     379          12 :       ReportInstantiationFailure(script, position, "Unexpected stdlib member");
     380          12 :       return MaybeHandle<Object>();
     381             :     }
     382             :   }
     383             : 
     384             :   // Check that a valid heap buffer is provided if required.
     385        4990 :   if (stdlib_use_of_typed_array_present) {
     386        1336 :     if (memory.is_null()) {
     387          12 :       ReportInstantiationFailure(script, position, "Requires heap buffer");
     388          12 :       return MaybeHandle<Object>();
     389             :     }
     390        1324 :     wasm_engine->memory_tracker()->MarkWasmMemoryNotGrowable(memory);
     391             :     size_t size = memory->byte_length();
     392             :     // Check the asm.js heap size against the valid limits.
     393        1324 :     if (!IsValidAsmjsMemorySize(size)) {
     394          84 :       ReportInstantiationFailure(script, position, "Invalid heap size");
     395          84 :       return MaybeHandle<Object>();
     396             :     }
     397             :   } else {
     398             :     memory = Handle<JSArrayBuffer>::null();
     399             :   }
     400             : 
     401        4894 :   wasm::ErrorThrower thrower(isolate, "AsmJs::Instantiate");
     402             :   MaybeHandle<Object> maybe_module_object =
     403        4894 :       wasm_engine->SyncInstantiate(isolate, &thrower, module, foreign, memory);
     404        4894 :   if (maybe_module_object.is_null()) {
     405             :     // An exception caused by the module start function will be set as pending
     406             :     // and bypass the {ErrorThrower}, this happens in case of a stack overflow.
     407          47 :     if (isolate->has_pending_exception()) isolate->clear_pending_exception();
     408          47 :     if (thrower.error()) {
     409             :       ScopedVector<char> error_reason(100);
     410          43 :       SNPrintF(error_reason, "Internal wasm failure: %s", thrower.error_msg());
     411          43 :       ReportInstantiationFailure(script, position, error_reason.start());
     412             :     } else {
     413           4 :       ReportInstantiationFailure(script, position, "Internal wasm failure");
     414             :     }
     415          47 :     thrower.Reset();  // Ensure exceptions do not propagate.
     416          47 :     return MaybeHandle<Object>();
     417             :   }
     418             :   DCHECK(!thrower.error());
     419        4847 :   Handle<Object> module_object = maybe_module_object.ToHandleChecked();
     420             : 
     421        4847 :   ReportInstantiationSuccess(script, position,
     422        9694 :                              instantiate_timer.Elapsed().InMillisecondsF());
     423             : 
     424             :   Handle<Name> single_function_name(
     425        4847 :       isolate->factory()->InternalizeUtf8String(AsmJs::kSingleFunctionName));
     426             :   MaybeHandle<Object> single_function =
     427        4847 :       Object::GetProperty(isolate, module_object, single_function_name);
     428        9694 :   if (!single_function.is_null() &&
     429             :       !single_function.ToHandleChecked()->IsUndefined(isolate)) {
     430         256 :     return single_function;
     431             :   }
     432             : 
     433             :   Handle<String> exports_name =
     434        4591 :       isolate->factory()->InternalizeUtf8String("exports");
     435        4591 :   return Object::GetProperty(isolate, module_object, exports_name);
     436             : }
     437             : 
     438             : }  // namespace internal
     439      122004 : }  // namespace v8

Generated by: LCOV version 1.10