LCOV - code coverage report
Current view: top level - test/cctest/wasm - test-run-wasm-module.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 433 437 99.1 %
Date: 2019-04-18 Functions: 41 43 95.3 %

          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 <stdlib.h>
       6             : #include <string.h>
       7             : 
       8             : #include "src/api-inl.h"
       9             : #include "src/objects-inl.h"
      10             : #include "src/snapshot/code-serializer.h"
      11             : #include "src/version.h"
      12             : #include "src/wasm/module-decoder.h"
      13             : #include "src/wasm/wasm-engine.h"
      14             : #include "src/wasm/wasm-memory.h"
      15             : #include "src/wasm/wasm-module-builder.h"
      16             : #include "src/wasm/wasm-module.h"
      17             : #include "src/wasm/wasm-objects-inl.h"
      18             : #include "src/wasm/wasm-opcodes.h"
      19             : 
      20             : #include "test/cctest/cctest.h"
      21             : #include "test/common/wasm/flag-utils.h"
      22             : #include "test/common/wasm/test-signatures.h"
      23             : #include "test/common/wasm/wasm-macro-gen.h"
      24             : #include "test/common/wasm/wasm-module-runner.h"
      25             : 
      26             : namespace v8 {
      27             : namespace internal {
      28             : namespace wasm {
      29             : namespace test_run_wasm_module {
      30             : 
      31             : using testing::CompileAndInstantiateForTesting;
      32             : 
      33             : namespace {
      34             : void Cleanup(Isolate* isolate = CcTest::InitIsolateOnce()) {
      35             :   // By sending a low memory notifications, we will try hard to collect all
      36             :   // garbage and will therefore also invoke all weak callbacks of actually
      37             :   // unreachable persistent handles.
      38         125 :   reinterpret_cast<v8::Isolate*>(isolate)->LowMemoryNotification();
      39             : }
      40             : 
      41         164 : void TestModule(Zone* zone, WasmModuleBuilder* builder,
      42             :                 int32_t expected_result) {
      43             :   ZoneBuffer buffer(zone);
      44         164 :   builder->WriteTo(buffer);
      45             : 
      46             :   Isolate* isolate = CcTest::InitIsolateOnce();
      47             :   HandleScope scope(isolate);
      48         164 :   testing::SetupIsolateForWasmModule(isolate);
      49             :   int32_t result =
      50         164 :       testing::CompileAndRunWasmModule(isolate, buffer.begin(), buffer.end());
      51         164 :   CHECK_EQ(expected_result, result);
      52         164 : }
      53             : 
      54           4 : void TestModuleException(Zone* zone, WasmModuleBuilder* builder) {
      55             :   ZoneBuffer buffer(zone);
      56           4 :   builder->WriteTo(buffer);
      57             : 
      58             :   Isolate* isolate = CcTest::InitIsolateOnce();
      59             :   HandleScope scope(isolate);
      60           4 :   testing::SetupIsolateForWasmModule(isolate);
      61           8 :   v8::TryCatch try_catch(reinterpret_cast<v8::Isolate*>(isolate));
      62           4 :   testing::CompileAndRunWasmModule(isolate, buffer.begin(), buffer.end());
      63           4 :   CHECK(try_catch.HasCaught());
      64             :   isolate->clear_pending_exception();
      65           4 : }
      66             : 
      67             : void ExportAsMain(WasmFunctionBuilder* f) {
      68         197 :   f->builder()->AddExport(CStrVector("main"), f);
      69             : }
      70             : 
      71             : #define EMIT_CODE_WITH_END(f, code)  \
      72             :   do {                               \
      73             :     f->EmitCode(code, sizeof(code)); \
      74             :     f->Emit(kExprEnd);               \
      75             :   } while (false)
      76             : 
      77             : }  // namespace
      78             : 
      79       26660 : TEST(Run_WasmModule_Return114) {
      80             :   {
      81             :     static const int32_t kReturnValue = 114;
      82           4 :     TestSignatures sigs;
      83           8 :     v8::internal::AccountingAllocator allocator;
      84           8 :     Zone zone(&allocator, ZONE_NAME);
      85             : 
      86           4 :     WasmModuleBuilder* builder = new (&zone) WasmModuleBuilder(&zone);
      87           4 :     WasmFunctionBuilder* f = builder->AddFunction(sigs.i_v());
      88             :     ExportAsMain(f);
      89           4 :     byte code[] = {WASM_I32V_2(kReturnValue)};
      90           4 :     EMIT_CODE_WITH_END(f, code);
      91           4 :     TestModule(&zone, builder, kReturnValue);
      92             :   }
      93             :   Cleanup();
      94           4 : }
      95             : 
      96       26660 : TEST(Run_WasmModule_CompilationHintsLazy) {
      97           4 :   if (!FLAG_wasm_tier_up || !FLAG_liftoff) return;
      98             :   {
      99             :     EXPERIMENTAL_FLAG_SCOPE(compilation_hints);
     100             : 
     101             :     static const int32_t kReturnValue = 114;
     102           3 :     TestSignatures sigs;
     103           6 :     v8::internal::AccountingAllocator allocator;
     104           6 :     Zone zone(&allocator, ZONE_NAME);
     105             : 
     106             :     // Build module with one lazy function.
     107           3 :     WasmModuleBuilder* builder = new (&zone) WasmModuleBuilder(&zone);
     108           3 :     WasmFunctionBuilder* f = builder->AddFunction(sigs.i_v());
     109             :     ExportAsMain(f);
     110           3 :     byte code[] = {WASM_I32V_2(kReturnValue)};
     111           3 :     EMIT_CODE_WITH_END(f, code);
     112             :     f->SetCompilationHint(WasmCompilationHintStrategy::kLazy,
     113             :                           WasmCompilationHintTier::kBaseline,
     114           3 :                           WasmCompilationHintTier::kOptimized);
     115             : 
     116             :     // Compile module. No function is actually compiled as the function is lazy.
     117             :     ZoneBuffer buffer(&zone);
     118           3 :     builder->WriteTo(buffer);
     119             :     Isolate* isolate = CcTest::InitIsolateOnce();
     120             :     HandleScope scope(isolate);
     121           3 :     testing::SetupIsolateForWasmModule(isolate);
     122           3 :     ErrorThrower thrower(isolate, "CompileAndRunWasmModule");
     123             :     MaybeHandle<WasmModuleObject> module = testing::CompileForTesting(
     124           3 :         isolate, &thrower, ModuleWireBytes(buffer.begin(), buffer.end()));
     125           3 :     CHECK(!module.is_null());
     126             : 
     127             :     // Lazy function was not invoked and therefore not compiled yet.
     128             :     int func_index = 0;
     129           3 :     NativeModule* native_module = module.ToHandleChecked()->native_module();
     130           3 :     CHECK(!native_module->HasCode(func_index));
     131             : 
     132             :     // Instantiate and invoke function.
     133             :     MaybeHandle<WasmInstanceObject> instance =
     134             :         isolate->wasm_engine()->SyncInstantiate(
     135           6 :             isolate, &thrower, module.ToHandleChecked(), {}, {});
     136           3 :     CHECK(!instance.is_null());
     137             :     int32_t result = testing::RunWasmModuleForTesting(
     138           3 :         isolate, instance.ToHandleChecked(), 0, nullptr);
     139           3 :     CHECK_EQ(kReturnValue, result);
     140             : 
     141             :     // Lazy function was invoked and therefore compiled.
     142           3 :     CHECK(native_module->HasCode(func_index));
     143           6 :     WasmCodeRefScope code_ref_scope;
     144           3 :     ExecutionTier actual_tier = native_module->GetCode(func_index)->tier();
     145             :     static_assert(ExecutionTier::kInterpreter < ExecutionTier::kLiftoff &&
     146             :                       ExecutionTier::kLiftoff < ExecutionTier::kTurbofan,
     147             :                   "Assume an order on execution tiers");
     148             :     ExecutionTier baseline_tier = ExecutionTier::kLiftoff;
     149           3 :     CHECK_LE(baseline_tier, actual_tier);
     150             :   }
     151             :   Cleanup();
     152             : }
     153             : 
     154       26660 : TEST(Run_WasmModule_CompilationHintsNoTiering) {
     155           4 :   if (!FLAG_wasm_tier_up || !FLAG_liftoff) return;
     156             :   {
     157             :     EXPERIMENTAL_FLAG_SCOPE(compilation_hints);
     158             : 
     159             :     static const int32_t kReturnValue = 114;
     160           3 :     TestSignatures sigs;
     161           6 :     v8::internal::AccountingAllocator allocator;
     162           6 :     Zone zone(&allocator, ZONE_NAME);
     163             : 
     164             :     // Build module with regularly compiled function (no tiering).
     165           3 :     WasmModuleBuilder* builder = new (&zone) WasmModuleBuilder(&zone);
     166           3 :     WasmFunctionBuilder* f = builder->AddFunction(sigs.i_v());
     167             :     ExportAsMain(f);
     168           3 :     byte code[] = {WASM_I32V_2(kReturnValue)};
     169           3 :     EMIT_CODE_WITH_END(f, code);
     170             :     f->SetCompilationHint(WasmCompilationHintStrategy::kEager,
     171             :                           WasmCompilationHintTier::kBaseline,
     172           3 :                           WasmCompilationHintTier::kBaseline);
     173             : 
     174             :     // Compile module.
     175             :     ZoneBuffer buffer(&zone);
     176           3 :     builder->WriteTo(buffer);
     177             :     Isolate* isolate = CcTest::InitIsolateOnce();
     178             :     HandleScope scope(isolate);
     179           3 :     testing::SetupIsolateForWasmModule(isolate);
     180           3 :     ErrorThrower thrower(isolate, "CompileAndRunWasmModule");
     181             :     MaybeHandle<WasmModuleObject> module = testing::CompileForTesting(
     182           3 :         isolate, &thrower, ModuleWireBytes(buffer.begin(), buffer.end()));
     183           3 :     CHECK(!module.is_null());
     184             : 
     185             :     // Synchronous compilation finished and no tiering units were initialized.
     186             :     int func_index = 0;
     187           3 :     NativeModule* native_module = module.ToHandleChecked()->native_module();
     188           3 :     CHECK(native_module->HasCode(func_index));
     189           6 :     WasmCodeRefScope code_ref_scope;
     190             :     ExecutionTier expected_tier = ExecutionTier::kLiftoff;
     191           3 :     ExecutionTier actual_tier = native_module->GetCode(func_index)->tier();
     192           3 :     CHECK_EQ(expected_tier, actual_tier);
     193             :   }
     194             :   Cleanup();
     195             : }
     196             : 
     197       26660 : TEST(Run_WasmModule_CompilationHintsTierUp) {
     198           4 :   if (!FLAG_wasm_tier_up || !FLAG_liftoff) return;
     199             :   {
     200             :     EXPERIMENTAL_FLAG_SCOPE(compilation_hints);
     201             : 
     202             :     static const int32_t kReturnValue = 114;
     203           3 :     TestSignatures sigs;
     204           6 :     v8::internal::AccountingAllocator allocator;
     205           6 :     Zone zone(&allocator, ZONE_NAME);
     206             : 
     207             :     // Build module with tiering compilation hint.
     208           3 :     WasmModuleBuilder* builder = new (&zone) WasmModuleBuilder(&zone);
     209           3 :     WasmFunctionBuilder* f = builder->AddFunction(sigs.i_v());
     210             :     ExportAsMain(f);
     211           3 :     byte code[] = {WASM_I32V_2(kReturnValue)};
     212           3 :     EMIT_CODE_WITH_END(f, code);
     213             :     f->SetCompilationHint(WasmCompilationHintStrategy::kEager,
     214             :                           WasmCompilationHintTier::kBaseline,
     215           3 :                           WasmCompilationHintTier::kOptimized);
     216             : 
     217             :     // Compile module.
     218             :     ZoneBuffer buffer(&zone);
     219           3 :     builder->WriteTo(buffer);
     220             :     Isolate* isolate = CcTest::InitIsolateOnce();
     221             :     HandleScope scope(isolate);
     222           3 :     testing::SetupIsolateForWasmModule(isolate);
     223           3 :     ErrorThrower thrower(isolate, "CompileAndRunWasmModule");
     224             :     MaybeHandle<WasmModuleObject> module = testing::CompileForTesting(
     225           3 :         isolate, &thrower, ModuleWireBytes(buffer.begin(), buffer.end()));
     226           3 :     CHECK(!module.is_null());
     227             : 
     228             :     // Expect code baseline code or top tier code.
     229             :     int func_index = 0;
     230           3 :     NativeModule* native_module = module.ToHandleChecked()->native_module();
     231           3 :     CHECK(native_module->HasCode(func_index));
     232           6 :     WasmCodeRefScope code_ref_scope;
     233           3 :     ExecutionTier actual_tier = native_module->GetCode(func_index)->tier();
     234             :     static_assert(ExecutionTier::kInterpreter < ExecutionTier::kLiftoff &&
     235             :                       ExecutionTier::kLiftoff < ExecutionTier::kTurbofan,
     236             :                   "Assume an order on execution tiers");
     237             :     ExecutionTier baseline_tier = ExecutionTier::kLiftoff;
     238           3 :     CHECK_LE(baseline_tier, actual_tier);
     239             :     ExecutionTier top_tier = ExecutionTier::kTurbofan;
     240           3 :     CHECK_LE(actual_tier, top_tier);
     241             :   }
     242             :   Cleanup();
     243             : }
     244             : 
     245       26660 : TEST(Run_WasmModule_CallAdd) {
     246             :   {
     247           8 :     v8::internal::AccountingAllocator allocator;
     248           8 :     Zone zone(&allocator, ZONE_NAME);
     249           4 :     TestSignatures sigs;
     250             : 
     251           4 :     WasmModuleBuilder* builder = new (&zone) WasmModuleBuilder(&zone);
     252             : 
     253           4 :     WasmFunctionBuilder* f1 = builder->AddFunction(sigs.i_ii());
     254             :     uint16_t param1 = 0;
     255             :     uint16_t param2 = 1;
     256             :     byte code1[] = {
     257           4 :         WASM_I32_ADD(WASM_GET_LOCAL(param1), WASM_GET_LOCAL(param2))};
     258           4 :     EMIT_CODE_WITH_END(f1, code1);
     259             : 
     260           4 :     WasmFunctionBuilder* f2 = builder->AddFunction(sigs.i_v());
     261             : 
     262             :     ExportAsMain(f2);
     263             :     byte code2[] = {
     264           4 :         WASM_CALL_FUNCTION(f1->func_index(), WASM_I32V_2(77), WASM_I32V_1(22))};
     265           4 :     EMIT_CODE_WITH_END(f2, code2);
     266           4 :     TestModule(&zone, builder, 99);
     267             :   }
     268             :   Cleanup();
     269           4 : }
     270             : 
     271       26660 : TEST(Run_WasmModule_ReadLoadedDataSegment) {
     272             :   {
     273             :     static const byte kDataSegmentDest0 = 12;
     274           8 :     v8::internal::AccountingAllocator allocator;
     275           8 :     Zone zone(&allocator, ZONE_NAME);
     276           4 :     TestSignatures sigs;
     277             : 
     278           4 :     WasmModuleBuilder* builder = new (&zone) WasmModuleBuilder(&zone);
     279           4 :     WasmFunctionBuilder* f = builder->AddFunction(sigs.i_v());
     280             : 
     281             :     ExportAsMain(f);
     282             :     byte code[] = {
     283           4 :         WASM_LOAD_MEM(MachineType::Int32(), WASM_I32V_1(kDataSegmentDest0))};
     284           4 :     EMIT_CODE_WITH_END(f, code);
     285           4 :     byte data[] = {0xAA, 0xBB, 0xCC, 0xDD};
     286           4 :     builder->AddDataSegment(data, sizeof(data), kDataSegmentDest0);
     287           4 :     TestModule(&zone, builder, 0xDDCCBBAA);
     288             :   }
     289             :   Cleanup();
     290           4 : }
     291             : 
     292       26660 : TEST(Run_WasmModule_CheckMemoryIsZero) {
     293             :   {
     294             :     static const int kCheckSize = 16 * 1024;
     295           8 :     v8::internal::AccountingAllocator allocator;
     296           8 :     Zone zone(&allocator, ZONE_NAME);
     297           4 :     TestSignatures sigs;
     298             : 
     299           4 :     WasmModuleBuilder* builder = new (&zone) WasmModuleBuilder(&zone);
     300           4 :     WasmFunctionBuilder* f = builder->AddFunction(sigs.i_v());
     301             : 
     302           4 :     uint16_t localIndex = f->AddLocal(kWasmI32);
     303             :     ExportAsMain(f);
     304           4 :     byte code[] = {WASM_BLOCK_I(
     305             :         WASM_WHILE(
     306             :             WASM_I32_LTS(WASM_GET_LOCAL(localIndex), WASM_I32V_3(kCheckSize)),
     307             :             WASM_IF_ELSE(
     308             :                 WASM_LOAD_MEM(MachineType::Int32(), WASM_GET_LOCAL(localIndex)),
     309             :                 WASM_BRV(3, WASM_I32V_1(-1)),
     310             :                 WASM_INC_LOCAL_BY(localIndex, 4))),
     311           8 :         WASM_I32V_1(11))};
     312           4 :     EMIT_CODE_WITH_END(f, code);
     313           4 :     TestModule(&zone, builder, 11);
     314             :   }
     315             :   Cleanup();
     316           4 : }
     317             : 
     318       26660 : TEST(Run_WasmModule_CallMain_recursive) {
     319             :   {
     320           8 :     v8::internal::AccountingAllocator allocator;
     321           8 :     Zone zone(&allocator, ZONE_NAME);
     322           4 :     TestSignatures sigs;
     323             : 
     324           4 :     WasmModuleBuilder* builder = new (&zone) WasmModuleBuilder(&zone);
     325           4 :     WasmFunctionBuilder* f = builder->AddFunction(sigs.i_v());
     326             : 
     327           4 :     uint16_t localIndex = f->AddLocal(kWasmI32);
     328             :     ExportAsMain(f);
     329             :     byte code[] = {
     330           4 :         WASM_SET_LOCAL(localIndex,
     331             :                        WASM_LOAD_MEM(MachineType::Int32(), WASM_ZERO)),
     332           4 :         WASM_IF_ELSE_I(WASM_I32_LTS(WASM_GET_LOCAL(localIndex), WASM_I32V_1(5)),
     333             :                        WASM_SEQ(WASM_STORE_MEM(MachineType::Int32(), WASM_ZERO,
     334             :                                                WASM_INC_LOCAL(localIndex)),
     335             :                                 WASM_CALL_FUNCTION0(0)),
     336          12 :                        WASM_I32V_1(55))};
     337           4 :     EMIT_CODE_WITH_END(f, code);
     338           4 :     TestModule(&zone, builder, 55);
     339             :   }
     340             :   Cleanup();
     341           4 : }
     342             : 
     343       26660 : TEST(Run_WasmModule_Global) {
     344             :   {
     345           8 :     v8::internal::AccountingAllocator allocator;
     346           8 :     Zone zone(&allocator, ZONE_NAME);
     347           4 :     TestSignatures sigs;
     348             : 
     349           4 :     WasmModuleBuilder* builder = new (&zone) WasmModuleBuilder(&zone);
     350           4 :     uint32_t global1 = builder->AddGlobal(kWasmI32, false);
     351           4 :     uint32_t global2 = builder->AddGlobal(kWasmI32, false);
     352           4 :     WasmFunctionBuilder* f1 = builder->AddFunction(sigs.i_v());
     353             :     byte code1[] = {
     354           4 :         WASM_I32_ADD(WASM_GET_GLOBAL(global1), WASM_GET_GLOBAL(global2))};
     355           4 :     EMIT_CODE_WITH_END(f1, code1);
     356           4 :     WasmFunctionBuilder* f2 = builder->AddFunction(sigs.i_v());
     357             :     ExportAsMain(f2);
     358             :     byte code2[] = {WASM_SET_GLOBAL(global1, WASM_I32V_1(56)),
     359             :                     WASM_SET_GLOBAL(global2, WASM_I32V_1(41)),
     360           4 :                     WASM_RETURN1(WASM_CALL_FUNCTION0(f1->func_index()))};
     361           4 :     EMIT_CODE_WITH_END(f2, code2);
     362           4 :     TestModule(&zone, builder, 97);
     363             :   }
     364             :   Cleanup();
     365           4 : }
     366             : 
     367       26660 : TEST(MemorySize) {
     368             :   {
     369             :     // Initial memory size is 16, see wasm-module-builder.cc
     370             :     static const int kExpectedValue = 16;
     371           4 :     TestSignatures sigs;
     372           8 :     v8::internal::AccountingAllocator allocator;
     373           8 :     Zone zone(&allocator, ZONE_NAME);
     374             : 
     375           4 :     WasmModuleBuilder* builder = new (&zone) WasmModuleBuilder(&zone);
     376           4 :     WasmFunctionBuilder* f = builder->AddFunction(sigs.i_v());
     377             :     ExportAsMain(f);
     378           4 :     byte code[] = {WASM_MEMORY_SIZE};
     379           4 :     EMIT_CODE_WITH_END(f, code);
     380           4 :     TestModule(&zone, builder, kExpectedValue);
     381             :   }
     382             :   Cleanup();
     383           4 : }
     384             : 
     385       26660 : TEST(Run_WasmModule_MemSize_GrowMem) {
     386             :   {
     387             :     // Initial memory size = 16 + MemoryGrow(10)
     388             :     static const int kExpectedValue = 26;
     389           4 :     TestSignatures sigs;
     390           8 :     v8::internal::AccountingAllocator allocator;
     391           8 :     Zone zone(&allocator, ZONE_NAME);
     392             : 
     393           4 :     WasmModuleBuilder* builder = new (&zone) WasmModuleBuilder(&zone);
     394           4 :     WasmFunctionBuilder* f = builder->AddFunction(sigs.i_v());
     395             :     ExportAsMain(f);
     396             :     byte code[] = {WASM_GROW_MEMORY(WASM_I32V_1(10)), WASM_DROP,
     397           4 :                    WASM_MEMORY_SIZE};
     398           4 :     EMIT_CODE_WITH_END(f, code);
     399           4 :     TestModule(&zone, builder, kExpectedValue);
     400             :   }
     401             :   Cleanup();
     402           4 : }
     403             : 
     404       26660 : TEST(MemoryGrowZero) {
     405             :   {
     406             :     // Initial memory size is 16, see wasm-module-builder.cc
     407             :     static const int kExpectedValue = 16;
     408           4 :     TestSignatures sigs;
     409           8 :     v8::internal::AccountingAllocator allocator;
     410           8 :     Zone zone(&allocator, ZONE_NAME);
     411             : 
     412           4 :     WasmModuleBuilder* builder = new (&zone) WasmModuleBuilder(&zone);
     413           4 :     WasmFunctionBuilder* f = builder->AddFunction(sigs.i_v());
     414             :     ExportAsMain(f);
     415           4 :     byte code[] = {WASM_GROW_MEMORY(WASM_I32V(0))};
     416           4 :     EMIT_CODE_WITH_END(f, code);
     417           4 :     TestModule(&zone, builder, kExpectedValue);
     418             :   }
     419             :   Cleanup();
     420           4 : }
     421             : 
     422           4 : class InterruptThread : public v8::base::Thread {
     423             :  public:
     424             :   explicit InterruptThread(Isolate* isolate, int32_t* memory)
     425             :       : Thread(Options("TestInterruptLoop")),
     426             :         isolate_(isolate),
     427           4 :         memory_(memory) {}
     428             : 
     429           4 :   static void OnInterrupt(v8::Isolate* isolate, void* data) {
     430             :     int32_t* m = reinterpret_cast<int32_t*>(data);
     431             :     // Set the interrupt location to 0 to break the loop in {TestInterruptLoop}.
     432             :     Address ptr = reinterpret_cast<Address>(&m[interrupt_location_]);
     433             :     WriteLittleEndianValue<int32_t>(ptr, interrupt_value_);
     434           4 :   }
     435             : 
     436           4 :   void Run() override {
     437             :     // Wait for the main thread to write the signal value.
     438           4 :     int32_t val = 0;
     439             :     do {
     440           4 :       val = memory_[0];
     441             :       val = ReadLittleEndianValue<int32_t>(reinterpret_cast<Address>(&val));
     442           4 :     } while (val != signal_value_);
     443           4 :     isolate_->RequestInterrupt(&OnInterrupt, const_cast<int32_t*>(memory_));
     444           4 :   }
     445             : 
     446             :   Isolate* isolate_;
     447             :   volatile int32_t* memory_;
     448             :   static const int32_t interrupt_location_ = 10;
     449             :   static const int32_t interrupt_value_ = 154;
     450             :   static const int32_t signal_value_ = 1221;
     451             : };
     452             : 
     453       26660 : TEST(TestInterruptLoop) {
     454             :   {
     455             :     // Do not dump the module of this test because it contains an infinite loop.
     456             :     if (FLAG_dump_wasm_module) return;
     457             : 
     458             :     // This test tests that WebAssembly loops can be interrupted, i.e. that if
     459             :     // an
     460             :     // InterruptCallback is registered by {Isolate::RequestInterrupt}, then the
     461             :     // InterruptCallback is eventually called even if a loop in WebAssembly code
     462             :     // is executed.
     463             :     // Test setup:
     464             :     // The main thread executes a WebAssembly function with a loop. In the loop
     465             :     // {signal_value_} is written to memory to signal a helper thread that the
     466             :     // main thread reached the loop in the WebAssembly program. When the helper
     467             :     // thread reads {signal_value_} from memory, it registers the
     468             :     // InterruptCallback. Upon exeution, the InterruptCallback write into the
     469             :     // WebAssemblyMemory to end the loop in the WebAssembly program.
     470           4 :     TestSignatures sigs;
     471             :     Isolate* isolate = CcTest::InitIsolateOnce();
     472           8 :     v8::internal::AccountingAllocator allocator;
     473           8 :     Zone zone(&allocator, ZONE_NAME);
     474             : 
     475           4 :     WasmModuleBuilder* builder = new (&zone) WasmModuleBuilder(&zone);
     476           4 :     WasmFunctionBuilder* f = builder->AddFunction(sigs.i_v());
     477             :     ExportAsMain(f);
     478             :     byte code[] = {
     479           8 :         WASM_LOOP(
     480             :             WASM_IFB(WASM_NOT(WASM_LOAD_MEM(
     481             :                          MachineType::Int32(),
     482             :                          WASM_I32V(InterruptThread::interrupt_location_ * 4))),
     483             :                      WASM_STORE_MEM(MachineType::Int32(), WASM_ZERO,
     484             :                                     WASM_I32V(InterruptThread::signal_value_)),
     485             :                      WASM_BR(1))),
     486          12 :         WASM_I32V(121)};
     487           4 :     EMIT_CODE_WITH_END(f, code);
     488             :     ZoneBuffer buffer(&zone);
     489           4 :     builder->WriteTo(buffer);
     490             : 
     491             :     HandleScope scope(isolate);
     492           4 :     testing::SetupIsolateForWasmModule(isolate);
     493           4 :     ErrorThrower thrower(isolate, "Test");
     494             :     const Handle<WasmInstanceObject> instance =
     495           8 :         CompileAndInstantiateForTesting(
     496           4 :             isolate, &thrower, ModuleWireBytes(buffer.begin(), buffer.end()))
     497             :             .ToHandleChecked();
     498             : 
     499             :     Handle<JSArrayBuffer> memory(instance->memory_object()->array_buffer(),
     500             :                                  isolate);
     501             :     int32_t* memory_array = reinterpret_cast<int32_t*>(memory->backing_store());
     502             : 
     503             :     InterruptThread thread(isolate, memory_array);
     504           4 :     thread.Start();
     505           4 :     testing::RunWasmModuleForTesting(isolate, instance, 0, nullptr);
     506             :     Address address = reinterpret_cast<Address>(
     507             :         &memory_array[InterruptThread::interrupt_location_]);
     508           4 :     CHECK_EQ(InterruptThread::interrupt_value_,
     509             :              ReadLittleEndianValue<int32_t>(address));
     510             :   }
     511             :   Cleanup();
     512             : }
     513             : 
     514       26660 : TEST(Run_WasmModule_MemoryGrowInIf) {
     515             :   {
     516           4 :     TestSignatures sigs;
     517           8 :     v8::internal::AccountingAllocator allocator;
     518           8 :     Zone zone(&allocator, ZONE_NAME);
     519           4 :     WasmModuleBuilder* builder = new (&zone) WasmModuleBuilder(&zone);
     520           4 :     WasmFunctionBuilder* f = builder->AddFunction(sigs.i_v());
     521             :     ExportAsMain(f);
     522             :     byte code[] = {WASM_IF_ELSE_I(WASM_I32V(0), WASM_GROW_MEMORY(WASM_I32V(1)),
     523           4 :                                   WASM_I32V(12))};
     524           4 :     EMIT_CODE_WITH_END(f, code);
     525           4 :     TestModule(&zone, builder, 12);
     526             :   }
     527             :   Cleanup();
     528           4 : }
     529             : 
     530       26660 : TEST(Run_WasmModule_GrowMemOobOffset) {
     531             :   {
     532             :     static const int kPageSize = 0x10000;
     533             :     // Initial memory size = 16 + MemoryGrow(10)
     534             :     static const int index = kPageSize * 17 + 4;
     535             :     int value = 0xACED;
     536           4 :     TestSignatures sigs;
     537           8 :     v8::internal::AccountingAllocator allocator;
     538           8 :     Zone zone(&allocator, ZONE_NAME);
     539             : 
     540           4 :     WasmModuleBuilder* builder = new (&zone) WasmModuleBuilder(&zone);
     541           4 :     WasmFunctionBuilder* f = builder->AddFunction(sigs.i_v());
     542             :     ExportAsMain(f);
     543             :     byte code[] = {WASM_GROW_MEMORY(WASM_I32V_1(1)),
     544           4 :                    WASM_STORE_MEM(MachineType::Int32(), WASM_I32V(index),
     545           8 :                                   WASM_I32V(value))};
     546           4 :     EMIT_CODE_WITH_END(f, code);
     547           4 :     TestModuleException(&zone, builder);
     548             :   }
     549             :   Cleanup();
     550           4 : }
     551             : 
     552       26660 : TEST(Run_WasmModule_GrowMemOobFixedIndex) {
     553             :   {
     554             :     static const int kPageSize = 0x10000;
     555             :     // Initial memory size = 16 + MemoryGrow(10)
     556             :     static const int index = kPageSize * 26 + 4;
     557             :     int value = 0xACED;
     558           4 :     TestSignatures sigs;
     559             :     Isolate* isolate = CcTest::InitIsolateOnce();
     560           8 :     Zone zone(isolate->allocator(), ZONE_NAME);
     561             : 
     562           4 :     WasmModuleBuilder* builder = new (&zone) WasmModuleBuilder(&zone);
     563           4 :     WasmFunctionBuilder* f = builder->AddFunction(sigs.i_i());
     564             :     ExportAsMain(f);
     565             :     byte code[] = {WASM_GROW_MEMORY(WASM_GET_LOCAL(0)), WASM_DROP,
     566           4 :                    WASM_STORE_MEM(MachineType::Int32(), WASM_I32V(index),
     567             :                                   WASM_I32V(value)),
     568           8 :                    WASM_LOAD_MEM(MachineType::Int32(), WASM_I32V(index))};
     569           4 :     EMIT_CODE_WITH_END(f, code);
     570             : 
     571             :     HandleScope scope(isolate);
     572             :     ZoneBuffer buffer(&zone);
     573           4 :     builder->WriteTo(buffer);
     574           4 :     testing::SetupIsolateForWasmModule(isolate);
     575             : 
     576           4 :     ErrorThrower thrower(isolate, "Test");
     577             :     Handle<WasmInstanceObject> instance =
     578           8 :         CompileAndInstantiateForTesting(
     579           4 :             isolate, &thrower, ModuleWireBytes(buffer.begin(), buffer.end()))
     580           4 :             .ToHandleChecked();
     581             : 
     582             :     // Initial memory size is 16 pages, should trap till index > MemSize on
     583             :     // consecutive GrowMem calls
     584          36 :     for (uint32_t i = 1; i < 5; i++) {
     585          16 :       Handle<Object> params[1] = {Handle<Object>(Smi::FromInt(i), isolate)};
     586          32 :       v8::TryCatch try_catch(reinterpret_cast<v8::Isolate*>(isolate));
     587          16 :       testing::RunWasmModuleForTesting(isolate, instance, 1, params);
     588          16 :       CHECK(try_catch.HasCaught());
     589             :       isolate->clear_pending_exception();
     590             :     }
     591             : 
     592             :     Handle<Object> params[1] = {Handle<Object>(Smi::FromInt(1), isolate)};
     593             :     int32_t result =
     594           4 :         testing::RunWasmModuleForTesting(isolate, instance, 1, params);
     595           4 :     CHECK_EQ(0xACED, result);
     596             :   }
     597             :   Cleanup();
     598           4 : }
     599             : 
     600       26660 : TEST(Run_WasmModule_GrowMemOobVariableIndex) {
     601             :   {
     602             :     static const int kPageSize = 0x10000;
     603             :     int value = 0xACED;
     604           4 :     TestSignatures sigs;
     605             :     Isolate* isolate = CcTest::InitIsolateOnce();
     606           8 :     v8::internal::AccountingAllocator allocator;
     607           8 :     Zone zone(&allocator, ZONE_NAME);
     608             : 
     609           4 :     WasmModuleBuilder* builder = new (&zone) WasmModuleBuilder(&zone);
     610           4 :     WasmFunctionBuilder* f = builder->AddFunction(sigs.i_i());
     611             :     ExportAsMain(f);
     612             :     byte code[] = {WASM_GROW_MEMORY(WASM_I32V_1(1)), WASM_DROP,
     613           4 :                    WASM_STORE_MEM(MachineType::Int32(), WASM_GET_LOCAL(0),
     614             :                                   WASM_I32V(value)),
     615           8 :                    WASM_LOAD_MEM(MachineType::Int32(), WASM_GET_LOCAL(0))};
     616           4 :     EMIT_CODE_WITH_END(f, code);
     617             : 
     618             :     HandleScope scope(isolate);
     619             :     ZoneBuffer buffer(&zone);
     620           4 :     builder->WriteTo(buffer);
     621           4 :     testing::SetupIsolateForWasmModule(isolate);
     622             : 
     623           4 :     ErrorThrower thrower(isolate, "Test");
     624             :     Handle<WasmInstanceObject> instance =
     625           8 :         CompileAndInstantiateForTesting(
     626           4 :             isolate, &thrower, ModuleWireBytes(buffer.begin(), buffer.end()))
     627           4 :             .ToHandleChecked();
     628             : 
     629             :     // Initial memory size is 16 pages, should trap till index > MemSize on
     630             :     // consecutive GrowMem calls
     631          36 :     for (int i = 1; i < 5; i++) {
     632             :       Handle<Object> params[1] = {
     633          16 :           Handle<Object>(Smi::FromInt((16 + i) * kPageSize - 3), isolate)};
     634          32 :       v8::TryCatch try_catch(reinterpret_cast<v8::Isolate*>(isolate));
     635          16 :       testing::RunWasmModuleForTesting(isolate, instance, 1, params);
     636          16 :       CHECK(try_catch.HasCaught());
     637             :       isolate->clear_pending_exception();
     638             :     }
     639             : 
     640          36 :     for (int i = 1; i < 5; i++) {
     641             :       Handle<Object> params[1] = {
     642          16 :           Handle<Object>(Smi::FromInt((20 + i) * kPageSize - 4), isolate)};
     643             :       int32_t result =
     644          16 :           testing::RunWasmModuleForTesting(isolate, instance, 1, params);
     645          16 :       CHECK_EQ(0xACED, result);
     646             :     }
     647             : 
     648           8 :     v8::TryCatch try_catch(reinterpret_cast<v8::Isolate*>(isolate));
     649             :     Handle<Object> params[1] = {
     650             :         Handle<Object>(Smi::FromInt(25 * kPageSize), isolate)};
     651           4 :     testing::RunWasmModuleForTesting(isolate, instance, 1, params);
     652           4 :     CHECK(try_catch.HasCaught());
     653             :     isolate->clear_pending_exception();
     654             :   }
     655             :   Cleanup();
     656           4 : }
     657             : 
     658       26660 : TEST(Run_WasmModule_Global_init) {
     659             :   {
     660           8 :     v8::internal::AccountingAllocator allocator;
     661           8 :     Zone zone(&allocator, ZONE_NAME);
     662           4 :     TestSignatures sigs;
     663             : 
     664           4 :     WasmModuleBuilder* builder = new (&zone) WasmModuleBuilder(&zone);
     665             :     uint32_t global1 =
     666           4 :         builder->AddGlobal(kWasmI32, false, false, WasmInitExpr(777777));
     667             :     uint32_t global2 =
     668           4 :         builder->AddGlobal(kWasmI32, false, false, WasmInitExpr(222222));
     669           4 :     WasmFunctionBuilder* f1 = builder->AddFunction(sigs.i_v());
     670             :     byte code[] = {
     671           4 :         WASM_I32_ADD(WASM_GET_GLOBAL(global1), WASM_GET_GLOBAL(global2))};
     672           4 :     EMIT_CODE_WITH_END(f1, code);
     673             :     ExportAsMain(f1);
     674           4 :     TestModule(&zone, builder, 999999);
     675             :   }
     676             :   Cleanup();
     677           4 : }
     678             : 
     679             : template <typename CType>
     680          24 : static void RunWasmModuleGlobalInitTest(ValueType type, CType expected) {
     681             :   {
     682          48 :     v8::internal::AccountingAllocator allocator;
     683          48 :     Zone zone(&allocator, ZONE_NAME);
     684          24 :     TestSignatures sigs;
     685             : 
     686          24 :     ValueType types[] = {type};
     687             :     FunctionSig sig(1, 0, types);
     688             : 
     689         264 :     for (int padding = 0; padding < 5; padding++) {
     690             :       // Test with a simple initializer
     691         120 :       WasmModuleBuilder* builder = new (&zone) WasmModuleBuilder(&zone);
     692             : 
     693         600 :       for (int i = 0; i < padding; i++) {  // pad global before
     694         480 :         builder->AddGlobal(kWasmI32, false, false, WasmInitExpr(i + 20000));
     695             :       }
     696             :       uint32_t global =
     697         120 :           builder->AddGlobal(type, false, false, WasmInitExpr(expected));
     698         600 :       for (int i = 0; i < padding; i++) {  // pad global after
     699         480 :         builder->AddGlobal(kWasmI32, false, false, WasmInitExpr(i + 30000));
     700             :       }
     701             : 
     702         120 :       WasmFunctionBuilder* f1 = builder->AddFunction(&sig);
     703         120 :       byte code[] = {WASM_GET_GLOBAL(global)};
     704         120 :       EMIT_CODE_WITH_END(f1, code);
     705             :       ExportAsMain(f1);
     706         120 :       TestModule(&zone, builder, expected);
     707             :     }
     708             :   }
     709             :   Cleanup();
     710          24 : }
     711             : 
     712       26660 : TEST(Run_WasmModule_Global_i32) {
     713           4 :   RunWasmModuleGlobalInitTest<int32_t>(kWasmI32, -983489);
     714           4 :   RunWasmModuleGlobalInitTest<int32_t>(kWasmI32, 11223344);
     715           4 : }
     716             : 
     717       26660 : TEST(Run_WasmModule_Global_f32) {
     718           4 :   RunWasmModuleGlobalInitTest<float>(kWasmF32, -983.9f);
     719           4 :   RunWasmModuleGlobalInitTest<float>(kWasmF32, 1122.99f);
     720           4 : }
     721             : 
     722       26660 : TEST(Run_WasmModule_Global_f64) {
     723           4 :   RunWasmModuleGlobalInitTest<double>(kWasmF64, -833.9);
     724           4 :   RunWasmModuleGlobalInitTest<double>(kWasmF64, 86374.25);
     725           4 : }
     726             : 
     727       26660 : TEST(InitDataAtTheUpperLimit) {
     728             :   {
     729             :     Isolate* isolate = CcTest::InitIsolateOnce();
     730             :     HandleScope scope(isolate);
     731           4 :     testing::SetupIsolateForWasmModule(isolate);
     732             : 
     733           4 :     ErrorThrower thrower(isolate, "Run_WasmModule_InitDataAtTheUpperLimit");
     734             : 
     735             :     const byte data[] = {
     736             :         WASM_MODULE_HEADER,   // --
     737             :         kMemorySectionCode,   // --
     738             :         U32V_1(4),            // section size
     739             :         ENTRY_COUNT(1),       // --
     740             :         kHasMaximumFlag,      // --
     741             :         1,                    // initial size
     742             :         2,                    // maximum size
     743             :         kDataSectionCode,     // --
     744             :         U32V_1(9),            // section size
     745             :         ENTRY_COUNT(1),       // --
     746             :         0,                    // linear memory index
     747             :         WASM_I32V_3(0xFFFF),  // destination offset
     748             :         kExprEnd,
     749             :         U32V_1(1),  // source size
     750             :         'c'         // data bytes
     751           4 :     };
     752             : 
     753             :     CompileAndInstantiateForTesting(
     754           4 :         isolate, &thrower, ModuleWireBytes(data, data + arraysize(data)));
     755           4 :     if (thrower.error()) {
     756           0 :       thrower.Reify()->Print();
     757           0 :       FATAL("compile or instantiate error");
     758             :     }
     759             :   }
     760             :   Cleanup();
     761           4 : }
     762             : 
     763       26660 : TEST(EmptyMemoryNonEmptyDataSegment) {
     764             :   {
     765             :     Isolate* isolate = CcTest::InitIsolateOnce();
     766             :     HandleScope scope(isolate);
     767           4 :     testing::SetupIsolateForWasmModule(isolate);
     768             : 
     769           4 :     ErrorThrower thrower(isolate, "Run_WasmModule_InitDataAtTheUpperLimit");
     770             : 
     771             :     const byte data[] = {
     772             :         WASM_MODULE_HEADER,  // --
     773             :         kMemorySectionCode,  // --
     774             :         U32V_1(4),           // section size
     775             :         ENTRY_COUNT(1),      // --
     776             :         kHasMaximumFlag,     // --
     777             :         0,                   // initial size
     778             :         0,                   // maximum size
     779             :         kDataSectionCode,    // --
     780             :         U32V_1(7),           // section size
     781             :         ENTRY_COUNT(1),      // --
     782             :         0,                   // linear memory index
     783             :         WASM_I32V_1(8),      // destination offset
     784             :         kExprEnd,
     785             :         U32V_1(1),  // source size
     786             :         'c'         // data bytes
     787           4 :     };
     788             : 
     789             :     CompileAndInstantiateForTesting(
     790           4 :         isolate, &thrower, ModuleWireBytes(data, data + arraysize(data)));
     791             :     // It should not be possible to instantiate this module.
     792           4 :     CHECK(thrower.error());
     793             :   }
     794             :   Cleanup();
     795           4 : }
     796             : 
     797       26660 : TEST(EmptyMemoryEmptyDataSegment) {
     798             :   {
     799             :     Isolate* isolate = CcTest::InitIsolateOnce();
     800             :     HandleScope scope(isolate);
     801           4 :     testing::SetupIsolateForWasmModule(isolate);
     802             : 
     803           4 :     ErrorThrower thrower(isolate, "Run_WasmModule_InitDataAtTheUpperLimit");
     804             : 
     805             :     const byte data[] = {
     806             :         WASM_MODULE_HEADER,  // --
     807             :         kMemorySectionCode,  // --
     808             :         U32V_1(4),           // section size
     809             :         ENTRY_COUNT(1),      // --
     810             :         kHasMaximumFlag,     // --
     811             :         0,                   // initial size
     812             :         0,                   // maximum size
     813             :         kDataSectionCode,    // --
     814             :         U32V_1(6),           // section size
     815             :         ENTRY_COUNT(1),      // --
     816             :         0,                   // linear memory index
     817             :         WASM_I32V_1(0),      // destination offset
     818             :         kExprEnd,
     819             :         U32V_1(0),  // source size
     820           4 :     };
     821             : 
     822             :     CompileAndInstantiateForTesting(
     823           4 :         isolate, &thrower, ModuleWireBytes(data, data + arraysize(data)));
     824             :     // It should be possible to instantiate this module.
     825           4 :     CHECK(!thrower.error());
     826             :   }
     827             :   Cleanup();
     828           4 : }
     829             : 
     830       26660 : TEST(MemoryWithOOBEmptyDataSegment) {
     831             :   {
     832             :     Isolate* isolate = CcTest::InitIsolateOnce();
     833             :     HandleScope scope(isolate);
     834           4 :     testing::SetupIsolateForWasmModule(isolate);
     835             : 
     836           4 :     ErrorThrower thrower(isolate, "Run_WasmModule_InitDataAtTheUpperLimit");
     837             : 
     838             :     const byte data[] = {
     839             :         WASM_MODULE_HEADER,      // --
     840             :         kMemorySectionCode,      // --
     841             :         U32V_1(4),               // section size
     842             :         ENTRY_COUNT(1),          // --
     843             :         kHasMaximumFlag,         // --
     844             :         1,                       // initial size
     845             :         1,                       // maximum size
     846             :         kDataSectionCode,        // --
     847             :         U32V_1(9),               // section size
     848             :         ENTRY_COUNT(1),          // --
     849             :         0,                       // linear memory index
     850             :         WASM_I32V_4(0x2468ACE),  // destination offset
     851             :         kExprEnd,
     852             :         U32V_1(0),  // source size
     853           4 :     };
     854             : 
     855             :     CompileAndInstantiateForTesting(
     856           4 :         isolate, &thrower, ModuleWireBytes(data, data + arraysize(data)));
     857             :     // It should not be possible to instantiate this module.
     858           4 :     CHECK(thrower.error());
     859             :   }
     860             :   Cleanup();
     861           4 : }
     862             : 
     863             : // Utility to free the allocated memory for a buffer that is manually
     864             : // externalized in a test.
     865             : struct ManuallyExternalizedBuffer {
     866             :   Isolate* isolate_;
     867             :   Handle<JSArrayBuffer> buffer_;
     868             :   void* allocation_base_;
     869             :   size_t allocation_length_;
     870             :   bool const should_free_;
     871             : 
     872           8 :   ManuallyExternalizedBuffer(JSArrayBuffer buffer, Isolate* isolate)
     873             :       : isolate_(isolate),
     874             :         buffer_(buffer, isolate),
     875           8 :         allocation_base_(buffer->allocation_base()),
     876           8 :         allocation_length_(buffer->allocation_length()),
     877          16 :         should_free_(!isolate_->wasm_engine()->memory_tracker()->IsWasmMemory(
     878          32 :             buffer->backing_store())) {
     879          16 :     if (!isolate_->wasm_engine()->memory_tracker()->IsWasmMemory(
     880             :             buffer->backing_store())) {
     881           0 :       v8::Utils::ToLocal(buffer_)->Externalize();
     882             :     }
     883           8 :   }
     884           8 :   ~ManuallyExternalizedBuffer() {
     885           8 :     if (should_free_) {
     886           0 :       buffer_->FreeBackingStoreFromMainThread();
     887             :     }
     888             :   }
     889             : };
     890             : 
     891       26660 : TEST(Run_WasmModule_Buffer_Externalized_GrowMem) {
     892             :   {
     893             :     Isolate* isolate = CcTest::InitIsolateOnce();
     894             :     HandleScope scope(isolate);
     895           4 :     TestSignatures sigs;
     896           8 :     v8::internal::AccountingAllocator allocator;
     897           8 :     Zone zone(&allocator, ZONE_NAME);
     898             : 
     899           4 :     WasmModuleBuilder* builder = new (&zone) WasmModuleBuilder(&zone);
     900           4 :     WasmFunctionBuilder* f = builder->AddFunction(sigs.i_v());
     901             :     ExportAsMain(f);
     902             :     byte code[] = {WASM_GROW_MEMORY(WASM_I32V_1(6)), WASM_DROP,
     903           4 :                    WASM_MEMORY_SIZE};
     904           4 :     EMIT_CODE_WITH_END(f, code);
     905             : 
     906             :     ZoneBuffer buffer(&zone);
     907           4 :     builder->WriteTo(buffer);
     908           4 :     testing::SetupIsolateForWasmModule(isolate);
     909           4 :     ErrorThrower thrower(isolate, "Test");
     910             :     const Handle<WasmInstanceObject> instance =
     911           8 :         CompileAndInstantiateForTesting(
     912           4 :             isolate, &thrower, ModuleWireBytes(buffer.begin(), buffer.end()))
     913             :             .ToHandleChecked();
     914             :     Handle<WasmMemoryObject> memory_object(instance->memory_object(), isolate);
     915             : 
     916             :     // Fake the Embedder flow by externalizing the array buffer.
     917           4 :     ManuallyExternalizedBuffer buffer1(memory_object->array_buffer(), isolate);
     918             : 
     919             :     // Grow using the API.
     920           4 :     uint32_t result = WasmMemoryObject::Grow(isolate, memory_object, 4);
     921           4 :     CHECK_EQ(16, result);
     922           4 :     CHECK(buffer1.buffer_->was_detached());  // growing always detaches
     923           4 :     CHECK_EQ(0, buffer1.buffer_->byte_length());
     924             : 
     925           4 :     CHECK_NE(*buffer1.buffer_, memory_object->array_buffer());
     926             : 
     927             :     // Fake the Embedder flow by externalizing the array buffer.
     928           4 :     ManuallyExternalizedBuffer buffer2(memory_object->array_buffer(), isolate);
     929             : 
     930             :     // Grow using an internal WASM bytecode.
     931           4 :     result = testing::RunWasmModuleForTesting(isolate, instance, 0, nullptr);
     932           4 :     CHECK_EQ(26, result);
     933           4 :     CHECK(buffer2.buffer_->was_detached());  // growing always detaches
     934           4 :     CHECK_EQ(0, buffer2.buffer_->byte_length());
     935           4 :     CHECK_NE(*buffer2.buffer_, memory_object->array_buffer());
     936             :   }
     937             :   Cleanup();
     938           4 : }
     939             : 
     940       26660 : TEST(Run_WasmModule_Buffer_Externalized_GrowMemMemSize) {
     941             :   {
     942             :     Isolate* isolate = CcTest::InitIsolateOnce();
     943             :     HandleScope scope(isolate);
     944             :     Handle<JSArrayBuffer> buffer;
     945           8 :     CHECK(wasm::NewArrayBuffer(isolate, 16 * kWasmPageSize).ToHandle(&buffer));
     946             :     Handle<WasmMemoryObject> mem_obj =
     947           4 :         WasmMemoryObject::New(isolate, buffer, 100);
     948           4 :     auto const contents = v8::Utils::ToLocal(buffer)->Externalize();
     949           4 :     int32_t result = WasmMemoryObject::Grow(isolate, mem_obj, 0);
     950           4 :     CHECK_EQ(16, result);
     951             :     constexpr bool is_wasm_memory = true;
     952             :     const JSArrayBuffer::Allocation allocation{contents.AllocationBase(),
     953             :                                                contents.AllocationLength(),
     954             :                                                contents.Data(), is_wasm_memory};
     955           4 :     JSArrayBuffer::FreeBackingStore(isolate, allocation);
     956             :   }
     957             :   Cleanup();
     958           4 : }
     959             : 
     960       26660 : TEST(Run_WasmModule_Buffer_Externalized_Detach) {
     961             :   {
     962             :     // Regression test for
     963             :     // https://bugs.chromium.org/p/chromium/issues/detail?id=731046
     964             :     Isolate* isolate = CcTest::InitIsolateOnce();
     965             :     HandleScope scope(isolate);
     966             :     Handle<JSArrayBuffer> buffer;
     967           8 :     CHECK(wasm::NewArrayBuffer(isolate, 16 * kWasmPageSize).ToHandle(&buffer));
     968           4 :     auto const contents = v8::Utils::ToLocal(buffer)->Externalize();
     969           4 :     wasm::DetachMemoryBuffer(isolate, buffer, true);
     970             :     constexpr bool is_wasm_memory = true;
     971             :     const JSArrayBuffer::Allocation allocation{contents.AllocationBase(),
     972             :                                                contents.AllocationLength(),
     973             :                                                contents.Data(), is_wasm_memory};
     974           4 :     JSArrayBuffer::FreeBackingStore(isolate, allocation);
     975             :   }
     976             :   Cleanup();
     977           4 : }
     978             : 
     979       26660 : TEST(Run_WasmModule_Buffer_Externalized_Regression_UseAfterFree) {
     980             :   // Regresion test for https://crbug.com/813876
     981             :   Isolate* isolate = CcTest::InitIsolateOnce();
     982             :   HandleScope scope(isolate);
     983             :   Handle<JSArrayBuffer> buffer;
     984           8 :   CHECK(wasm::NewArrayBuffer(isolate, 16 * kWasmPageSize).ToHandle(&buffer));
     985           4 :   Handle<WasmMemoryObject> mem = WasmMemoryObject::New(isolate, buffer, 128);
     986           4 :   auto contents = v8::Utils::ToLocal(buffer)->Externalize();
     987           4 :   WasmMemoryObject::Grow(isolate, mem, 0);
     988             :   constexpr bool is_wasm_memory = true;
     989           4 :   JSArrayBuffer::FreeBackingStore(
     990             :       isolate, JSArrayBuffer::Allocation(contents.AllocationBase(),
     991             :                                          contents.AllocationLength(),
     992           4 :                                          contents.Data(), is_wasm_memory));
     993             :   // Make sure we can write to the buffer without crashing
     994             :   uint32_t* int_buffer =
     995             :       reinterpret_cast<uint32_t*>(mem->array_buffer()->backing_store());
     996           4 :   int_buffer[0] = 0;
     997           4 : }
     998             : 
     999             : #if V8_TARGET_ARCH_64_BIT
    1000       26660 : TEST(Run_WasmModule_Reclaim_Memory) {
    1001             :   // Make sure we can allocate memories without running out of address space.
    1002             :   Isolate* isolate = CcTest::InitIsolateOnce();
    1003             :   Handle<JSArrayBuffer> buffer;
    1004        2052 :   for (int i = 0; i < 256; ++i) {
    1005             :     HandleScope scope(isolate);
    1006        2048 :     CHECK(NewArrayBuffer(isolate, kWasmPageSize).ToHandle(&buffer));
    1007             :   }
    1008           4 : }
    1009             : #endif
    1010             : 
    1011       26660 : TEST(AtomicOpDisassembly) {
    1012             :   {
    1013             :     EXPERIMENTAL_FLAG_SCOPE(threads);
    1014           4 :     TestSignatures sigs;
    1015             :     Isolate* isolate = CcTest::InitIsolateOnce();
    1016           8 :     v8::internal::AccountingAllocator allocator;
    1017           8 :     Zone zone(&allocator, ZONE_NAME);
    1018             : 
    1019           4 :     WasmModuleBuilder* builder = new (&zone) WasmModuleBuilder(&zone);
    1020           4 :     builder->SetHasSharedMemory();
    1021           4 :     builder->SetMaxMemorySize(16);
    1022           4 :     WasmFunctionBuilder* f = builder->AddFunction(sigs.i_i());
    1023             :     ExportAsMain(f);
    1024             :     byte code[] = {
    1025             :         WASM_ATOMICS_STORE_OP(kExprI32AtomicStore, WASM_ZERO, WASM_GET_LOCAL(0),
    1026             :                               MachineRepresentation::kWord32),
    1027             :         WASM_ATOMICS_LOAD_OP(kExprI32AtomicLoad, WASM_ZERO,
    1028           4 :                              MachineRepresentation::kWord32)};
    1029           4 :     EMIT_CODE_WITH_END(f, code);
    1030             : 
    1031             :     HandleScope scope(isolate);
    1032             :     ZoneBuffer buffer(&zone);
    1033           4 :     builder->WriteTo(buffer);
    1034           4 :     testing::SetupIsolateForWasmModule(isolate);
    1035             : 
    1036           4 :     ErrorThrower thrower(isolate, "Test");
    1037           4 :     auto enabled_features = WasmFeaturesFromIsolate(isolate);
    1038             :     MaybeHandle<WasmModuleObject> module_object =
    1039             :         isolate->wasm_engine()->SyncCompile(
    1040             :             isolate, enabled_features, &thrower,
    1041           4 :             ModuleWireBytes(buffer.begin(), buffer.end()));
    1042             : 
    1043           4 :     module_object.ToHandleChecked()->DisassembleFunction(0);
    1044             :   }
    1045             :   Cleanup();
    1046           4 : }
    1047             : 
    1048             : #undef EMIT_CODE_WITH_END
    1049             : 
    1050             : }  // namespace test_run_wasm_module
    1051             : }  // namespace wasm
    1052             : }  // namespace internal
    1053       79968 : }  // namespace v8

Generated by: LCOV version 1.10