OLD | NEW |
1 // Copyright 2015 the V8 project authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include <stdlib.h> | 5 #include <stdlib.h> |
6 #include <string.h> | 6 #include <string.h> |
7 | 7 |
8 #include "src/wasm/module-decoder.h" | 8 #include "src/wasm/module-decoder.h" |
9 #include "src/wasm/wasm-macro-gen.h" | 9 #include "src/wasm/wasm-macro-gen.h" |
10 #include "src/wasm/wasm-module-builder.h" | 10 #include "src/wasm/wasm-module-builder.h" |
(...skipping 292 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
303 Zone zone(&allocator); | 303 Zone zone(&allocator); |
304 | 304 |
305 WasmModuleBuilder* builder = new (&zone) WasmModuleBuilder(&zone); | 305 WasmModuleBuilder* builder = new (&zone) WasmModuleBuilder(&zone); |
306 WasmFunctionBuilder* f = builder->AddFunction(sigs.i_v()); | 306 WasmFunctionBuilder* f = builder->AddFunction(sigs.i_v()); |
307 ExportAsMain(f); | 307 ExportAsMain(f); |
308 byte code[] = {WASM_GROW_MEMORY(WASM_I32V(0))}; | 308 byte code[] = {WASM_GROW_MEMORY(WASM_I32V(0))}; |
309 f->EmitCode(code, sizeof(code)); | 309 f->EmitCode(code, sizeof(code)); |
310 TestModule(&zone, builder, kExpectedValue); | 310 TestModule(&zone, builder, kExpectedValue); |
311 } | 311 } |
312 | 312 |
| 313 class InterruptThread : public v8::base::Thread { |
| 314 public: |
| 315 explicit InterruptThread(Isolate* isolate, int32_t* memory) |
| 316 : Thread(Options("TestInterruptLoop")), |
| 317 isolate_(isolate), |
| 318 memory_(memory) {} |
| 319 |
| 320 static void OnInterrupt(v8::Isolate* isolate, void* data) { |
| 321 int32_t* m = reinterpret_cast<int32_t*>(data); |
| 322 // Set the interrupt location to 0 to break the loop in {TestInterruptLoop}. |
| 323 m[interrupt_location_] = interrupt_value_; |
| 324 } |
| 325 |
| 326 virtual void Run() { |
| 327 // Wait for the main thread to write the signal value. |
| 328 while (memory_[0] != signal_value_) { |
| 329 } |
| 330 isolate_->RequestInterrupt(&OnInterrupt, const_cast<int32_t*>(memory_)); |
| 331 } |
| 332 |
| 333 Isolate* isolate_; |
| 334 volatile int32_t* memory_; |
| 335 static const int32_t interrupt_location_ = 10; |
| 336 static const int32_t interrupt_value_ = 154; |
| 337 static const int32_t signal_value_ = 1221; |
| 338 }; |
| 339 |
| 340 TEST(TestInterruptLoop) { |
| 341 // This test tests that WebAssembly loops can be interrupted, i.e. that if an |
| 342 // InterruptCallback is registered by {Isolate::RequestInterrupt}, then the |
| 343 // InterruptCallback is eventually called even if a loop in WebAssembly code |
| 344 // is executed. |
| 345 // Test setup: |
| 346 // The main thread executes a WebAssembly function with a loop. In the loop |
| 347 // {signal_value_} is written to memory to signal a helper thread that the |
| 348 // main thread reached the loop in the WebAssembly program. When the helper |
| 349 // thread reads {signal_value_} from memory, it registers the |
| 350 // InterruptCallback. Upon exeution, the InterruptCallback write into the |
| 351 // WebAssemblyMemory to end the loop in the WebAssembly program. |
| 352 TestSignatures sigs; |
| 353 Isolate* isolate = CcTest::InitIsolateOnce(); |
| 354 v8::internal::AccountingAllocator allocator; |
| 355 Zone zone(&allocator); |
| 356 |
| 357 WasmModuleBuilder* builder = new (&zone) WasmModuleBuilder(&zone); |
| 358 WasmFunctionBuilder* f = builder->AddFunction(sigs.i_v()); |
| 359 ExportAsMain(f); |
| 360 byte code[] = {WASM_LOOP(WASM_IFB( |
| 361 WASM_NOT(WASM_LOAD_MEM( |
| 362 MachineType::Int32(), |
| 363 WASM_I32V(InterruptThread::interrupt_location_ * 4))), |
| 364 WASM_STORE_MEM(MachineType::Int32(), WASM_ZERO, |
| 365 WASM_I32V(InterruptThread::signal_value_)), |
| 366 WASM_BR(1))), |
| 367 WASM_I32V(121)}; |
| 368 f->EmitCode(code, sizeof(code)); |
| 369 ZoneBuffer buffer(&zone); |
| 370 builder->WriteTo(buffer); |
| 371 |
| 372 HandleScope scope(isolate); |
| 373 testing::SetupIsolateForWasmModule(isolate); |
| 374 ErrorThrower thrower(isolate, "Test"); |
| 375 const Handle<JSObject> instance = |
| 376 testing::CompileInstantiateWasmModuleForTesting( |
| 377 isolate, &thrower, &zone, buffer.begin(), buffer.end(), |
| 378 ModuleOrigin::kWasmOrigin); |
| 379 CHECK(!instance.is_null()); |
| 380 |
| 381 MaybeHandle<JSArrayBuffer> maybe_memory = |
| 382 GetInstanceMemory(isolate, instance); |
| 383 Handle<JSArrayBuffer> memory = maybe_memory.ToHandleChecked(); |
| 384 int32_t* memory_array = reinterpret_cast<int32_t*>(memory->backing_store()); |
| 385 |
| 386 InterruptThread thread(isolate, memory_array); |
| 387 thread.Start(); |
| 388 testing::RunWasmModuleForTesting(isolate, instance, 0, nullptr, |
| 389 ModuleOrigin::kWasmOrigin); |
| 390 CHECK_EQ(InterruptThread::interrupt_value_, |
| 391 memory_array[InterruptThread::interrupt_location_]); |
| 392 } |
| 393 |
313 TEST(Run_WasmModule_GrowMemoryInIf) { | 394 TEST(Run_WasmModule_GrowMemoryInIf) { |
314 TestSignatures sigs; | 395 TestSignatures sigs; |
315 v8::internal::AccountingAllocator allocator; | 396 v8::internal::AccountingAllocator allocator; |
316 Zone zone(&allocator); | 397 Zone zone(&allocator); |
317 WasmModuleBuilder* builder = new (&zone) WasmModuleBuilder(&zone); | 398 WasmModuleBuilder* builder = new (&zone) WasmModuleBuilder(&zone); |
318 WasmFunctionBuilder* f = builder->AddFunction(sigs.i_v()); | 399 WasmFunctionBuilder* f = builder->AddFunction(sigs.i_v()); |
319 ExportAsMain(f); | 400 ExportAsMain(f); |
320 byte code[] = {WASM_IF_ELSE_I(WASM_I32V(0), WASM_GROW_MEMORY(WASM_I32V(1)), | 401 byte code[] = {WASM_IF_ELSE_I(WASM_I32V(0), WASM_GROW_MEMORY(WASM_I32V(1)), |
321 WASM_I32V(12))}; | 402 WASM_I32V(12))}; |
322 f->EmitCode(code, sizeof(code)); | 403 f->EmitCode(code, sizeof(code)); |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
358 WASM_GROW_MEMORY(WASM_GET_LOCAL(0)), WASM_DROP, | 439 WASM_GROW_MEMORY(WASM_GET_LOCAL(0)), WASM_DROP, |
359 WASM_STORE_MEM(MachineType::Int32(), WASM_I32V(index), WASM_I32V(value)), | 440 WASM_STORE_MEM(MachineType::Int32(), WASM_I32V(index), WASM_I32V(value)), |
360 WASM_LOAD_MEM(MachineType::Int32(), WASM_I32V(index))}; | 441 WASM_LOAD_MEM(MachineType::Int32(), WASM_I32V(index))}; |
361 f->EmitCode(code, sizeof(code)); | 442 f->EmitCode(code, sizeof(code)); |
362 | 443 |
363 HandleScope scope(isolate); | 444 HandleScope scope(isolate); |
364 ZoneBuffer buffer(&zone); | 445 ZoneBuffer buffer(&zone); |
365 builder->WriteTo(buffer); | 446 builder->WriteTo(buffer); |
366 testing::SetupIsolateForWasmModule(isolate); | 447 testing::SetupIsolateForWasmModule(isolate); |
367 | 448 |
| 449 ErrorThrower thrower(isolate, "Test"); |
368 Handle<JSObject> instance = testing::CompileInstantiateWasmModuleForTesting( | 450 Handle<JSObject> instance = testing::CompileInstantiateWasmModuleForTesting( |
369 isolate, &zone, buffer.begin(), buffer.end(), ModuleOrigin::kWasmOrigin); | 451 isolate, &thrower, &zone, buffer.begin(), buffer.end(), |
| 452 ModuleOrigin::kWasmOrigin); |
370 CHECK(!instance.is_null()); | 453 CHECK(!instance.is_null()); |
371 | 454 |
372 // Initial memory size is 16 pages, should trap till index > MemSize on | 455 // Initial memory size is 16 pages, should trap till index > MemSize on |
373 // consecutive GrowMem calls | 456 // consecutive GrowMem calls |
374 for (uint32_t i = 1; i < 5; i++) { | 457 for (uint32_t i = 1; i < 5; i++) { |
375 Handle<Object> params[1] = {Handle<Object>(Smi::FromInt(i), isolate)}; | 458 Handle<Object> params[1] = {Handle<Object>(Smi::FromInt(i), isolate)}; |
376 v8::TryCatch try_catch(reinterpret_cast<v8::Isolate*>(isolate)); | 459 v8::TryCatch try_catch(reinterpret_cast<v8::Isolate*>(isolate)); |
377 testing::RunWasmModuleForTesting(isolate, instance, 1, params, | 460 testing::RunWasmModuleForTesting(isolate, instance, 1, params, |
378 ModuleOrigin::kWasmOrigin); | 461 ModuleOrigin::kWasmOrigin); |
379 CHECK(try_catch.HasCaught()); | 462 CHECK(try_catch.HasCaught()); |
(...skipping 21 matching lines...) Expand all Loading... |
401 WASM_GROW_MEMORY(WASM_I8(1)), WASM_DROP, | 484 WASM_GROW_MEMORY(WASM_I8(1)), WASM_DROP, |
402 WASM_STORE_MEM(MachineType::Int32(), WASM_GET_LOCAL(0), WASM_I32V(value)), | 485 WASM_STORE_MEM(MachineType::Int32(), WASM_GET_LOCAL(0), WASM_I32V(value)), |
403 WASM_LOAD_MEM(MachineType::Int32(), WASM_GET_LOCAL(0))}; | 486 WASM_LOAD_MEM(MachineType::Int32(), WASM_GET_LOCAL(0))}; |
404 f->EmitCode(code, sizeof(code)); | 487 f->EmitCode(code, sizeof(code)); |
405 | 488 |
406 HandleScope scope(isolate); | 489 HandleScope scope(isolate); |
407 ZoneBuffer buffer(&zone); | 490 ZoneBuffer buffer(&zone); |
408 builder->WriteTo(buffer); | 491 builder->WriteTo(buffer); |
409 testing::SetupIsolateForWasmModule(isolate); | 492 testing::SetupIsolateForWasmModule(isolate); |
410 | 493 |
| 494 ErrorThrower thrower(isolate, "Test"); |
411 Handle<JSObject> instance = testing::CompileInstantiateWasmModuleForTesting( | 495 Handle<JSObject> instance = testing::CompileInstantiateWasmModuleForTesting( |
412 isolate, &zone, buffer.begin(), buffer.end(), ModuleOrigin::kWasmOrigin); | 496 isolate, &thrower, &zone, buffer.begin(), buffer.end(), |
| 497 ModuleOrigin::kWasmOrigin); |
413 | 498 |
414 CHECK(!instance.is_null()); | 499 CHECK(!instance.is_null()); |
415 | 500 |
416 // Initial memory size is 16 pages, should trap till index > MemSize on | 501 // Initial memory size is 16 pages, should trap till index > MemSize on |
417 // consecutive GrowMem calls | 502 // consecutive GrowMem calls |
418 for (int i = 1; i < 5; i++) { | 503 for (int i = 1; i < 5; i++) { |
419 Handle<Object> params[1] = { | 504 Handle<Object> params[1] = { |
420 Handle<Object>(Smi::FromInt((16 + i) * kPageSize - 3), isolate)}; | 505 Handle<Object>(Smi::FromInt((16 + i) * kPageSize - 3), isolate)}; |
421 v8::TryCatch try_catch(reinterpret_cast<v8::Isolate*>(isolate)); | 506 v8::TryCatch try_catch(reinterpret_cast<v8::Isolate*>(isolate)); |
422 testing::RunWasmModuleForTesting(isolate, instance, 1, params, | 507 testing::RunWasmModuleForTesting(isolate, instance, 1, params, |
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
525 | 610 |
526 TEST(Run_WasmModule_Global_f32) { | 611 TEST(Run_WasmModule_Global_f32) { |
527 RunWasmModuleGlobalInitTest<float>(kAstF32, -983.9f); | 612 RunWasmModuleGlobalInitTest<float>(kAstF32, -983.9f); |
528 RunWasmModuleGlobalInitTest<float>(kAstF32, 1122.99f); | 613 RunWasmModuleGlobalInitTest<float>(kAstF32, 1122.99f); |
529 } | 614 } |
530 | 615 |
531 TEST(Run_WasmModule_Global_f64) { | 616 TEST(Run_WasmModule_Global_f64) { |
532 RunWasmModuleGlobalInitTest<double>(kAstF64, -833.9); | 617 RunWasmModuleGlobalInitTest<double>(kAstF64, -833.9); |
533 RunWasmModuleGlobalInitTest<double>(kAstF64, 86374.25); | 618 RunWasmModuleGlobalInitTest<double>(kAstF64, 86374.25); |
534 } | 619 } |
OLD | NEW |