diff options
Diffstat (limited to 'deps/v8/src/runtime/runtime-wasm.cc')
-rw-r--r-- | deps/v8/src/runtime/runtime-wasm.cc | 142 |
1 files changed, 114 insertions, 28 deletions
diff --git a/deps/v8/src/runtime/runtime-wasm.cc b/deps/v8/src/runtime/runtime-wasm.cc index ab69046c45..3ae5b92da1 100644 --- a/deps/v8/src/runtime/runtime-wasm.cc +++ b/deps/v8/src/runtime/runtime-wasm.cc @@ -14,52 +14,115 @@ #include "src/objects-inl.h" #include "src/v8memory.h" #include "src/wasm/wasm-module.h" +#include "src/wasm/wasm-objects.h" +#include "src/wasm/wasm-opcodes.h" namespace v8 { namespace internal { +namespace { +Handle<WasmInstanceObject> GetWasmInstanceOnStackTop(Isolate* isolate) { + DisallowHeapAllocation no_allocation; + const Address entry = Isolate::c_entry_fp(isolate->thread_local_top()); + Address pc = + Memory::Address_at(entry + StandardFrameConstants::kCallerPCOffset); + Code* code = isolate->inner_pointer_to_code_cache()->GetCacheEntry(pc)->code; + DCHECK_EQ(Code::WASM_FUNCTION, code->kind()); + WasmInstanceObject* owning_instance = wasm::GetOwningWasmInstance(code); + CHECK_NOT_NULL(owning_instance); + return handle(owning_instance, isolate); +} +} // namespace + RUNTIME_FUNCTION(Runtime_WasmMemorySize) { HandleScope scope(isolate); DCHECK_EQ(0, args.length()); - Handle<JSObject> module_instance; - { - // Get the module JSObject - DisallowHeapAllocation no_allocation; - const Address entry = Isolate::c_entry_fp(isolate->thread_local_top()); - Address pc = - Memory::Address_at(entry + StandardFrameConstants::kCallerPCOffset); - Code* code = - isolate->inner_pointer_to_code_cache()->GetCacheEntry(pc)->code; - Object* owning_instance = wasm::GetOwningWasmInstance(code); - CHECK_NOT_NULL(owning_instance); - module_instance = handle(JSObject::cast(owning_instance), isolate); - } + Handle<WasmInstanceObject> instance = GetWasmInstanceOnStackTop(isolate); return *isolate->factory()->NewNumberFromInt( - wasm::GetInstanceMemorySize(isolate, module_instance)); + wasm::GetInstanceMemorySize(isolate, instance)); } RUNTIME_FUNCTION(Runtime_WasmGrowMemory) { HandleScope scope(isolate); DCHECK_EQ(1, args.length()); CONVERT_UINT32_ARG_CHECKED(delta_pages, 0); - Handle<JSObject> module_instance; - { - // Get the module JSObject - DisallowHeapAllocation no_allocation; - const Address entry = Isolate::c_entry_fp(isolate->thread_local_top()); - Address pc = - Memory::Address_at(entry + StandardFrameConstants::kCallerPCOffset); - Code* code = - isolate->inner_pointer_to_code_cache()->GetCacheEntry(pc)->code; - Object* owning_instance = wasm::GetOwningWasmInstance(code); - CHECK_NOT_NULL(owning_instance); - module_instance = handle(JSObject::cast(owning_instance), isolate); - } + Handle<WasmInstanceObject> instance = GetWasmInstanceOnStackTop(isolate); return *isolate->factory()->NewNumberFromInt( - wasm::GrowInstanceMemory(isolate, module_instance, delta_pages)); + wasm::GrowMemory(isolate, instance, delta_pages)); +} + +Object* ThrowRuntimeError(Isolate* isolate, int message_id, int byte_offset, + bool patch_source_position) { + HandleScope scope(isolate); + Handle<Object> error_obj = isolate->factory()->NewWasmRuntimeError( + static_cast<MessageTemplate::Template>(message_id)); + + if (!patch_source_position) { + return isolate->Throw(*error_obj); + } + + // For wasm traps, the byte offset (a.k.a source position) can not be + // determined from relocation info, since the explicit checks for traps + // converge in one singe block which calls this runtime function. + // We hence pass the byte offset explicitely, and patch it into the top-most + // frame (a wasm frame) on the collected stack trace. + // TODO(wasm): This implementation is temporary, see bug #5007: + // https://bugs.chromium.org/p/v8/issues/detail?id=5007 + Handle<JSObject> error = Handle<JSObject>::cast(error_obj); + Handle<Object> stack_trace_obj = JSReceiver::GetDataProperty( + error, isolate->factory()->stack_trace_symbol()); + // Patch the stack trace (array of <receiver, function, code, position>). + if (stack_trace_obj->IsJSArray()) { + Handle<FrameArray> stack_elements( + FrameArray::cast(JSArray::cast(*stack_trace_obj)->elements())); + DCHECK(stack_elements->Code(0)->kind() == AbstractCode::WASM_FUNCTION); + DCHECK(stack_elements->Offset(0)->value() >= 0); + stack_elements->SetOffset(0, Smi::FromInt(-1 - byte_offset)); + } + + // Patch the detailed stack trace (array of JSObjects with various + // properties). + Handle<Object> detailed_stack_trace_obj = JSReceiver::GetDataProperty( + error, isolate->factory()->detailed_stack_trace_symbol()); + if (detailed_stack_trace_obj->IsJSArray()) { + Handle<FixedArray> stack_elements( + FixedArray::cast(JSArray::cast(*detailed_stack_trace_obj)->elements())); + DCHECK_GE(stack_elements->length(), 1); + Handle<JSObject> top_frame(JSObject::cast(stack_elements->get(0))); + Handle<String> wasm_offset_key = + isolate->factory()->InternalizeOneByteString( + STATIC_CHAR_VECTOR("column")); + LookupIterator it(top_frame, wasm_offset_key, top_frame, + LookupIterator::PROTOTYPE_CHAIN_SKIP_INTERCEPTOR); + if (it.IsFound()) { + DCHECK(JSReceiver::GetDataProperty(&it)->IsSmi()); + // Make column number 1-based here. + Maybe<bool> data_set = JSReceiver::SetDataProperty( + &it, handle(Smi::FromInt(byte_offset + 1), isolate)); + DCHECK(data_set.IsJust() && data_set.FromJust() == true); + USE(data_set); + } + } + + return isolate->Throw(*error_obj); +} + +RUNTIME_FUNCTION(Runtime_ThrowWasmError) { + DCHECK_EQ(2, args.length()); + CONVERT_SMI_ARG_CHECKED(message_id, 0); + CONVERT_SMI_ARG_CHECKED(byte_offset, 1); + return ThrowRuntimeError(isolate, message_id, byte_offset, true); } +#define DECLARE_ENUM(name) \ + RUNTIME_FUNCTION(Runtime_ThrowWasm##name) { \ + int message_id = wasm::WasmOpcodes::TrapReasonToMessageId(wasm::k##name); \ + return ThrowRuntimeError(isolate, message_id, 0, false); \ + } +FOREACH_WASM_TRAPREASON(DECLARE_ENUM) +#undef DECLARE_ENUM + RUNTIME_FUNCTION(Runtime_WasmThrowTypeError) { HandleScope scope(isolate); DCHECK_EQ(0, args.length()); @@ -89,5 +152,28 @@ RUNTIME_FUNCTION(Runtime_WasmGetCaughtExceptionValue) { return exception; } +RUNTIME_FUNCTION(Runtime_WasmRunInterpreter) { + DCHECK(args.length() == 3); + HandleScope scope(isolate); + CONVERT_ARG_HANDLE_CHECKED(JSObject, instance_obj, 0); + CONVERT_NUMBER_CHECKED(int32_t, func_index, Int32, args[1]); + CONVERT_ARG_HANDLE_CHECKED(Object, arg_buffer_obj, 2); + CHECK(WasmInstanceObject::IsWasmInstanceObject(*instance_obj)); + + // The arg buffer is the raw pointer to the caller's stack. It looks like a + // Smi (lowest bit not set, as checked by IsSmi), but is no valid Smi. We just + // cast it back to the raw pointer. + CHECK(!arg_buffer_obj->IsHeapObject()); + CHECK(arg_buffer_obj->IsSmi()); + uint8_t* arg_buffer = reinterpret_cast<uint8_t*>(*arg_buffer_obj); + + Handle<WasmInstanceObject> instance = + Handle<WasmInstanceObject>::cast(instance_obj); + Handle<WasmDebugInfo> debug_info = + WasmInstanceObject::GetOrCreateDebugInfo(instance); + WasmDebugInfo::RunInterpreter(debug_info, func_index, arg_buffer); + return isolate->heap()->undefined_value(); +} + } // namespace internal } // namespace v8 |