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