// Copyright 2017 the V8 project authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #ifndef V8_WASM_WASM_OBJECTS_INL_H_ #define V8_WASM_WASM_OBJECTS_INL_H_ #include "src/wasm/wasm-objects.h" #include "src/contexts-inl.h" #include "src/heap/heap-write-barrier-inl.h" #include "src/objects/foreign-inl.h" #include "src/objects/heap-number-inl.h" #include "src/objects/js-array-buffer-inl.h" #include "src/objects/js-objects-inl.h" #include "src/objects/managed.h" #include "src/objects/oddball-inl.h" #include "src/objects/script-inl.h" #include "src/roots.h" #include "src/v8memory.h" #include "src/wasm/wasm-code-manager.h" #include "src/wasm/wasm-module.h" // Has to be the last include (doesn't have include guards) #include "src/objects/object-macros.h" namespace v8 { namespace internal { OBJECT_CONSTRUCTORS_IMPL(WasmExceptionObject, JSObject) OBJECT_CONSTRUCTORS_IMPL(WasmExceptionTag, Struct) OBJECT_CONSTRUCTORS_IMPL(WasmExportedFunctionData, Struct) OBJECT_CONSTRUCTORS_IMPL(WasmDebugInfo, Struct) OBJECT_CONSTRUCTORS_IMPL(WasmGlobalObject, JSObject) OBJECT_CONSTRUCTORS_IMPL(WasmInstanceObject, JSObject) OBJECT_CONSTRUCTORS_IMPL(WasmMemoryObject, JSObject) OBJECT_CONSTRUCTORS_IMPL(WasmModuleObject, JSObject) OBJECT_CONSTRUCTORS_IMPL(WasmTableObject, JSObject) OBJECT_CONSTRUCTORS_IMPL(AsmWasmData, Struct) NEVER_READ_ONLY_SPACE_IMPL(WasmDebugInfo) CAST_ACCESSOR(WasmDebugInfo) CAST_ACCESSOR(WasmExceptionObject) CAST_ACCESSOR(WasmExceptionTag) CAST_ACCESSOR(WasmExportedFunctionData) CAST_ACCESSOR(WasmGlobalObject) CAST_ACCESSOR(WasmInstanceObject) CAST_ACCESSOR(WasmMemoryObject) CAST_ACCESSOR(WasmModuleObject) CAST_ACCESSOR(WasmTableObject) CAST_ACCESSOR(AsmWasmData) #define OPTIONAL_ACCESSORS(holder, name, type, offset) \ bool holder::has_##name() { \ return !READ_FIELD(*this, offset)->IsUndefined(); \ } \ ACCESSORS(holder, name, type, offset) #define PRIMITIVE_ACCESSORS(holder, name, type, offset) \ type holder::name() const { \ if (COMPRESS_POINTERS_BOOL && alignof(type) > kTaggedSize) { \ /* TODO(ishell, v8:8875): When pointer compression is enabled 8-byte */ \ /* size fields (external pointers, doubles and BigInt data) are only */ \ /* kTaggedSize aligned so we have to use unaligned pointer friendly */ \ /* way of accessing them in order to avoid undefined behavior in C++ */ \ /* code. */ \ return ReadUnalignedValue(FIELD_ADDR(*this, offset)); \ } else { \ return *reinterpret_cast(FIELD_ADDR(*this, offset)); \ } \ } \ void holder::set_##name(type value) { \ if (COMPRESS_POINTERS_BOOL && alignof(type) > kTaggedSize) { \ /* TODO(ishell, v8:8875): When pointer compression is enabled 8-byte */ \ /* size fields (external pointers, doubles and BigInt data) are only */ \ /* kTaggedSize aligned so we have to use unaligned pointer friendly */ \ /* way of accessing them in order to avoid undefined behavior in C++ */ \ /* code. */ \ WriteUnalignedValue(FIELD_ADDR(*this, offset), value); \ } else { \ *reinterpret_cast(FIELD_ADDR(*this, offset)) = value; \ } \ } // WasmModuleObject ACCESSORS(WasmModuleObject, managed_native_module, Managed, kNativeModuleOffset) ACCESSORS(WasmModuleObject, export_wrappers, FixedArray, kExportWrappersOffset) ACCESSORS(WasmModuleObject, script, Script, kScriptOffset) ACCESSORS(WasmModuleObject, weak_instance_list, WeakArrayList, kWeakInstanceListOffset) OPTIONAL_ACCESSORS(WasmModuleObject, asm_js_offset_table, ByteArray, kAsmJsOffsetTableOffset) OPTIONAL_ACCESSORS(WasmModuleObject, breakpoint_infos, FixedArray, kBreakPointInfosOffset) wasm::NativeModule* WasmModuleObject::native_module() const { return managed_native_module()->raw(); } const std::shared_ptr& WasmModuleObject::shared_native_module() const { return managed_native_module()->get(); } const wasm::WasmModule* WasmModuleObject::module() const { // TODO(clemensh): Remove this helper (inline in callers). return native_module()->module(); } void WasmModuleObject::reset_breakpoint_infos() { WRITE_FIELD(*this, kBreakPointInfosOffset, GetReadOnlyRoots().undefined_value()); } bool WasmModuleObject::is_asm_js() { bool asm_js = module()->origin == wasm::kAsmJsOrigin; DCHECK_EQ(asm_js, script()->IsUserJavaScript()); DCHECK_EQ(asm_js, has_asm_js_offset_table()); return asm_js; } // WasmTableObject ACCESSORS(WasmTableObject, elements, FixedArray, kElementsOffset) ACCESSORS(WasmTableObject, maximum_length, Object, kMaximumLengthOffset) ACCESSORS(WasmTableObject, dispatch_tables, FixedArray, kDispatchTablesOffset) SMI_ACCESSORS(WasmTableObject, raw_type, kRawTypeOffset) // WasmMemoryObject ACCESSORS(WasmMemoryObject, array_buffer, JSArrayBuffer, kArrayBufferOffset) SMI_ACCESSORS(WasmMemoryObject, maximum_pages, kMaximumPagesOffset) OPTIONAL_ACCESSORS(WasmMemoryObject, instances, WeakArrayList, kInstancesOffset) // WasmGlobalObject ACCESSORS(WasmGlobalObject, untagged_buffer, JSArrayBuffer, kUntaggedBufferOffset) ACCESSORS(WasmGlobalObject, tagged_buffer, FixedArray, kTaggedBufferOffset) SMI_ACCESSORS(WasmGlobalObject, offset, kOffsetOffset) SMI_ACCESSORS(WasmGlobalObject, flags, kFlagsOffset) BIT_FIELD_ACCESSORS(WasmGlobalObject, flags, type, WasmGlobalObject::TypeBits) BIT_FIELD_ACCESSORS(WasmGlobalObject, flags, is_mutable, WasmGlobalObject::IsMutableBit) int WasmGlobalObject::type_size() const { return wasm::ValueTypes::ElementSizeInBytes(type()); } Address WasmGlobalObject::address() const { DCHECK_NE(type(), wasm::kWasmAnyRef); DCHECK_LE(offset() + type_size(), untagged_buffer()->byte_length()); return Address(untagged_buffer()->backing_store()) + offset(); } int32_t WasmGlobalObject::GetI32() { return ReadLittleEndianValue(address()); } int64_t WasmGlobalObject::GetI64() { return ReadLittleEndianValue(address()); } float WasmGlobalObject::GetF32() { return ReadLittleEndianValue(address()); } double WasmGlobalObject::GetF64() { return ReadLittleEndianValue(address()); } Handle WasmGlobalObject::GetRef() { // We use this getter for anyref, anyfunc, and except_ref. DCHECK(wasm::ValueTypes::IsReferenceType(type())); return handle(tagged_buffer()->get(offset()), GetIsolate()); } void WasmGlobalObject::SetI32(int32_t value) { WriteLittleEndianValue(address(), value); } void WasmGlobalObject::SetI64(int64_t value) { WriteLittleEndianValue(address(), value); } void WasmGlobalObject::SetF32(float value) { WriteLittleEndianValue(address(), value); } void WasmGlobalObject::SetF64(double value) { WriteLittleEndianValue(address(), value); } void WasmGlobalObject::SetAnyRef(Handle value) { // We use this getter anyref and except_ref. DCHECK(type() == wasm::kWasmAnyRef || type() == wasm::kWasmExceptRef); tagged_buffer()->set(offset(), *value); } bool WasmGlobalObject::SetAnyFunc(Isolate* isolate, Handle value) { DCHECK_EQ(type(), wasm::kWasmAnyFunc); if (!value->IsNull(isolate) && !WasmExportedFunction::IsWasmExportedFunction(*value)) { return false; } tagged_buffer()->set(offset(), *value); return true; } // WasmInstanceObject PRIMITIVE_ACCESSORS(WasmInstanceObject, memory_start, byte*, kMemoryStartOffset) PRIMITIVE_ACCESSORS(WasmInstanceObject, memory_size, size_t, kMemorySizeOffset) PRIMITIVE_ACCESSORS(WasmInstanceObject, memory_mask, size_t, kMemoryMaskOffset) PRIMITIVE_ACCESSORS(WasmInstanceObject, isolate_root, Address, kIsolateRootOffset) PRIMITIVE_ACCESSORS(WasmInstanceObject, stack_limit_address, Address, kStackLimitAddressOffset) PRIMITIVE_ACCESSORS(WasmInstanceObject, real_stack_limit_address, Address, kRealStackLimitAddressOffset) PRIMITIVE_ACCESSORS(WasmInstanceObject, imported_function_targets, Address*, kImportedFunctionTargetsOffset) PRIMITIVE_ACCESSORS(WasmInstanceObject, globals_start, byte*, kGlobalsStartOffset) PRIMITIVE_ACCESSORS(WasmInstanceObject, imported_mutable_globals, Address*, kImportedMutableGlobalsOffset) PRIMITIVE_ACCESSORS(WasmInstanceObject, indirect_function_table_size, uint32_t, kIndirectFunctionTableSizeOffset) PRIMITIVE_ACCESSORS(WasmInstanceObject, indirect_function_table_sig_ids, uint32_t*, kIndirectFunctionTableSigIdsOffset) PRIMITIVE_ACCESSORS(WasmInstanceObject, indirect_function_table_targets, Address*, kIndirectFunctionTableTargetsOffset) PRIMITIVE_ACCESSORS(WasmInstanceObject, jump_table_start, Address, kJumpTableStartOffset) PRIMITIVE_ACCESSORS(WasmInstanceObject, data_segment_starts, Address*, kDataSegmentStartsOffset) PRIMITIVE_ACCESSORS(WasmInstanceObject, data_segment_sizes, uint32_t*, kDataSegmentSizesOffset) PRIMITIVE_ACCESSORS(WasmInstanceObject, dropped_data_segments, byte*, kDroppedDataSegmentsOffset) PRIMITIVE_ACCESSORS(WasmInstanceObject, dropped_elem_segments, byte*, kDroppedElemSegmentsOffset) ACCESSORS(WasmInstanceObject, module_object, WasmModuleObject, kModuleObjectOffset) ACCESSORS(WasmInstanceObject, exports_object, JSObject, kExportsObjectOffset) ACCESSORS(WasmInstanceObject, native_context, Context, kNativeContextOffset) OPTIONAL_ACCESSORS(WasmInstanceObject, memory_object, WasmMemoryObject, kMemoryObjectOffset) OPTIONAL_ACCESSORS(WasmInstanceObject, untagged_globals_buffer, JSArrayBuffer, kUntaggedGlobalsBufferOffset) OPTIONAL_ACCESSORS(WasmInstanceObject, tagged_globals_buffer, FixedArray, kTaggedGlobalsBufferOffset) OPTIONAL_ACCESSORS(WasmInstanceObject, imported_mutable_globals_buffers, FixedArray, kImportedMutableGlobalsBuffersOffset) OPTIONAL_ACCESSORS(WasmInstanceObject, debug_info, WasmDebugInfo, kDebugInfoOffset) OPTIONAL_ACCESSORS(WasmInstanceObject, tables, FixedArray, kTablesOffset) ACCESSORS(WasmInstanceObject, imported_function_refs, FixedArray, kImportedFunctionRefsOffset) OPTIONAL_ACCESSORS(WasmInstanceObject, indirect_function_table_refs, FixedArray, kIndirectFunctionTableRefsOffset) OPTIONAL_ACCESSORS(WasmInstanceObject, managed_native_allocations, Foreign, kManagedNativeAllocationsOffset) OPTIONAL_ACCESSORS(WasmInstanceObject, exceptions_table, FixedArray, kExceptionsTableOffset) ACCESSORS(WasmInstanceObject, undefined_value, Oddball, kUndefinedValueOffset) ACCESSORS(WasmInstanceObject, null_value, Oddball, kNullValueOffset) ACCESSORS(WasmInstanceObject, centry_stub, Code, kCEntryStubOffset) OPTIONAL_ACCESSORS(WasmInstanceObject, wasm_exported_functions, FixedArray, kWasmExportedFunctionsOffset) inline bool WasmInstanceObject::has_indirect_function_table() { return indirect_function_table_sig_ids() != nullptr; } void WasmInstanceObject::clear_padding() { if (FIELD_SIZE(kOptionalPaddingOffset) != 0) { DCHECK_EQ(4, FIELD_SIZE(kOptionalPaddingOffset)); memset(reinterpret_cast(address() + kOptionalPaddingOffset), 0, FIELD_SIZE(kOptionalPaddingOffset)); } } IndirectFunctionTableEntry::IndirectFunctionTableEntry( Handle instance, int index) : instance_(instance), index_(index) { DCHECK_GE(index, 0); DCHECK_LT(index, instance->indirect_function_table_size()); } ImportedFunctionEntry::ImportedFunctionEntry( Handle instance, int index) : instance_(instance), index_(index) { DCHECK_GE(index, 0); DCHECK_LT(index, instance->module()->num_imported_functions); } // WasmExceptionObject ACCESSORS(WasmExceptionObject, serialized_signature, PodArray, kSerializedSignatureOffset) ACCESSORS(WasmExceptionObject, exception_tag, HeapObject, kExceptionTagOffset) // WasmExportedFunction WasmExportedFunction::WasmExportedFunction(Address ptr) : JSFunction(ptr) { SLOW_DCHECK(IsWasmExportedFunction(*this)); } CAST_ACCESSOR(WasmExportedFunction) // WasmExportedFunctionData ACCESSORS(WasmExportedFunctionData, wrapper_code, Code, kWrapperCodeOffset) ACCESSORS(WasmExportedFunctionData, instance, WasmInstanceObject, kInstanceOffset) SMI_ACCESSORS(WasmExportedFunctionData, jump_table_offset, kJumpTableOffsetOffset) SMI_ACCESSORS(WasmExportedFunctionData, function_index, kFunctionIndexOffset) // WasmDebugInfo ACCESSORS(WasmDebugInfo, wasm_instance, WasmInstanceObject, kInstanceOffset) ACCESSORS(WasmDebugInfo, interpreter_handle, Object, kInterpreterHandleOffset) ACCESSORS(WasmDebugInfo, interpreted_functions, FixedArray, kInterpretedFunctionsOffset) OPTIONAL_ACCESSORS(WasmDebugInfo, locals_names, FixedArray, kLocalsNamesOffset) OPTIONAL_ACCESSORS(WasmDebugInfo, c_wasm_entries, FixedArray, kCWasmEntriesOffset) OPTIONAL_ACCESSORS(WasmDebugInfo, c_wasm_entry_map, Managed, kCWasmEntryMapOffset) #undef OPTIONAL_ACCESSORS #undef READ_PRIMITIVE_FIELD #undef WRITE_PRIMITIVE_FIELD #undef PRIMITIVE_ACCESSORS uint32_t WasmTableObject::current_length() { return elements()->length(); } wasm::ValueType WasmTableObject::type() { return static_cast(raw_type()); } bool WasmMemoryObject::has_maximum_pages() { return maximum_pages() >= 0; } // WasmExceptionTag SMI_ACCESSORS(WasmExceptionTag, index, kIndexOffset) // AsmWasmData ACCESSORS(AsmWasmData, managed_native_module, Managed, kManagedNativeModuleOffset) ACCESSORS(AsmWasmData, export_wrappers, FixedArray, kExportWrappersOffset) ACCESSORS(AsmWasmData, asm_js_offset_table, ByteArray, kAsmJsOffsetTableOffset) ACCESSORS(AsmWasmData, uses_bitset, HeapNumber, kUsesBitsetOffset) #include "src/objects/object-macros-undef.h" } // namespace internal } // namespace v8 #endif // V8_WASM_WASM_OBJECTS_INL_H_