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 "src/wasm/wasm-objects.h" | 5 #include "src/wasm/wasm-objects.h" |
6 #include "src/utils.h" | 6 #include "src/utils.h" |
7 | 7 |
8 #include "src/assembler-inl.h" | 8 #include "src/assembler-inl.h" |
9 #include "src/base/iterator.h" | 9 #include "src/base/iterator.h" |
10 #include "src/compiler/wasm-compiler.h" | 10 #include "src/compiler/wasm-compiler.h" |
(...skipping 754 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
765 // WasmCompiledModule::cast would fail since fields are not set yet. | 765 // WasmCompiledModule::cast would fail since fields are not set yet. |
766 Handle<WasmCompiledModule> compiled_module( | 766 Handle<WasmCompiledModule> compiled_module( |
767 reinterpret_cast<WasmCompiledModule*>(*ret), isolate); | 767 reinterpret_cast<WasmCompiledModule*>(*ret), isolate); |
768 compiled_module->InitId(); | 768 compiled_module->InitId(); |
769 compiled_module->set_num_imported_functions(0); | 769 compiled_module->set_num_imported_functions(0); |
770 compiled_module->set_shared(shared); | 770 compiled_module->set_shared(shared); |
771 compiled_module->set_native_context(isolate->native_context()); | 771 compiled_module->set_native_context(isolate->native_context()); |
772 return compiled_module; | 772 return compiled_module; |
773 } | 773 } |
774 | 774 |
775 Handle<WasmCompiledModule> WasmCompiledModule::Clone( | |
776 Isolate* isolate, Handle<WasmCompiledModule> module) { | |
777 Handle<WasmCompiledModule> ret = Handle<WasmCompiledModule>::cast( | |
778 isolate->factory()->CopyFixedArray(module)); | |
779 ret->InitId(); | |
780 ret->reset_weak_owning_instance(); | |
781 ret->reset_weak_next_instance(); | |
782 ret->reset_weak_prev_instance(); | |
783 ret->reset_weak_exported_functions(); | |
784 if (ret->has_embedded_mem_start()) { | |
785 WasmCompiledModule::recreate_embedded_mem_start(ret, isolate->factory(), | |
786 ret->embedded_mem_start()); | |
787 } | |
788 if (ret->has_globals_start()) { | |
789 WasmCompiledModule::recreate_globals_start(ret, isolate->factory(), | |
790 ret->globals_start()); | |
791 } | |
792 if (ret->has_embedded_mem_size()) { | |
793 WasmCompiledModule::recreate_embedded_mem_size(ret, isolate->factory(), | |
794 ret->embedded_mem_size()); | |
795 } | |
796 return ret; | |
797 } | |
798 | |
799 void WasmCompiledModule::Reset(Isolate* isolate, | |
800 WasmCompiledModule* compiled_module) { | |
801 DisallowHeapAllocation no_gc; | |
802 TRACE("Resetting %d\n", compiled_module->instance_id()); | |
803 Object* undefined = *isolate->factory()->undefined_value(); | |
804 Object* fct_obj = compiled_module->ptr_to_code_table(); | |
805 if (fct_obj != nullptr && fct_obj != undefined) { | |
806 uint32_t old_mem_size = compiled_module->mem_size(); | |
807 uint32_t default_mem_size = compiled_module->default_mem_size(); | |
808 Address old_mem_start = compiled_module->GetEmbeddedMemStartOrNull(); | |
809 | |
810 // Patch code to update memory references, global references, and function | |
811 // table references. | |
812 Zone specialization_zone(isolate->allocator(), ZONE_NAME); | |
813 CodeSpecialization code_specialization(isolate, &specialization_zone); | |
814 | |
815 if (old_mem_size > 0 && old_mem_start != nullptr) { | |
816 code_specialization.RelocateMemoryReferences(old_mem_start, old_mem_size, | |
817 nullptr, default_mem_size); | |
818 } | |
819 | |
820 if (compiled_module->has_globals_start()) { | |
821 Address globals_start = | |
822 reinterpret_cast<Address>(compiled_module->globals_start()); | |
823 code_specialization.RelocateGlobals(globals_start, nullptr); | |
824 compiled_module->set_globals_start(0); | |
825 } | |
826 | |
827 // Reset function tables. | |
828 if (compiled_module->has_function_tables()) { | |
829 FixedArray* function_tables = compiled_module->ptr_to_function_tables(); | |
830 FixedArray* empty_function_tables = | |
831 compiled_module->ptr_to_empty_function_tables(); | |
832 if (function_tables != empty_function_tables) { | |
833 DCHECK_EQ(function_tables->length(), empty_function_tables->length()); | |
834 for (int i = 0, e = function_tables->length(); i < e; ++i) { | |
835 code_specialization.RelocateObject( | |
836 handle(function_tables->get(i), isolate), | |
837 handle(empty_function_tables->get(i), isolate)); | |
838 } | |
839 compiled_module->set_ptr_to_function_tables(empty_function_tables); | |
840 } | |
841 } | |
842 | |
843 FixedArray* functions = FixedArray::cast(fct_obj); | |
844 for (int i = compiled_module->num_imported_functions(), | |
845 end = functions->length(); | |
846 i < end; ++i) { | |
847 Code* code = Code::cast(functions->get(i)); | |
848 // Skip lazy compile stubs. | |
849 if (code->builtin_index() == Builtins::kWasmCompileLazy) continue; | |
850 if (code->kind() != Code::WASM_FUNCTION) { | |
851 // From here on, there should only be wrappers for exported functions. | |
852 for (; i < end; ++i) { | |
853 DCHECK_EQ(Code::JS_TO_WASM_FUNCTION, | |
854 Code::cast(functions->get(i))->kind()); | |
855 } | |
856 break; | |
857 } | |
858 bool changed = | |
859 code_specialization.ApplyToWasmCode(code, SKIP_ICACHE_FLUSH); | |
860 // TODO(wasm): Check if this is faster than passing FLUSH_ICACHE_IF_NEEDED | |
861 // above. | |
862 if (changed) { | |
863 Assembler::FlushICache(isolate, code->instruction_start(), | |
864 code->instruction_size()); | |
865 } | |
866 } | |
867 } | |
868 compiled_module->ResetSpecializationMemInfoIfNeeded(); | |
869 } | |
870 | |
775 void WasmCompiledModule::InitId() { | 871 void WasmCompiledModule::InitId() { |
776 #if DEBUG | 872 #if DEBUG |
777 static uint32_t instance_id_counter = 0; | 873 static uint32_t instance_id_counter = 0; |
778 set(kID_instance_id, Smi::FromInt(instance_id_counter++)); | 874 set(kID_instance_id, Smi::FromInt(instance_id_counter++)); |
779 TRACE("New compiled module id: %d\n", instance_id()); | 875 TRACE("New compiled module id: %d\n", instance_id()); |
780 #endif | 876 #endif |
781 } | 877 } |
782 | 878 |
879 void WasmCompiledModule::ResetSpecializationMemInfoIfNeeded() { | |
880 DisallowHeapAllocation no_gc; | |
881 if (has_embedded_mem_start()) { | |
882 set_embedded_mem_size(0); | |
883 set_embedded_mem_start(0); | |
884 } | |
885 } | |
886 | |
887 void WasmCompiledModule::SetSpecializationMemInfoFrom( | |
888 Factory* factory, Handle<WasmCompiledModule> compiled_module, | |
889 Handle<JSArrayBuffer> buffer) { | |
890 DCHECK(!buffer.is_null()); | |
891 size_t start_address = reinterpret_cast<size_t>(buffer->backing_store()); | |
892 uint32_t size = static_cast<uint32_t>(buffer->byte_length()->Number()); | |
893 if (!compiled_module->has_embedded_mem_start()) { | |
894 DCHECK(!compiled_module->has_embedded_mem_size()); | |
895 WasmCompiledModule::recreate_embedded_mem_start(compiled_module, factory, | |
896 start_address); | |
897 WasmCompiledModule::recreate_embedded_mem_size(compiled_module, factory, | |
898 size); | |
899 } else { | |
900 compiled_module->set_embedded_mem_start(start_address); | |
901 compiled_module->set_embedded_mem_size(size); | |
902 } | |
903 } | |
904 | |
905 void WasmCompiledModule::SetGlobalsStartAddressFrom( | |
906 Factory* factory, Handle<WasmCompiledModule> compiled_module, | |
907 Handle<JSArrayBuffer> buffer) { | |
908 DCHECK(!buffer.is_null()); | |
909 size_t start_address = reinterpret_cast<size_t>(buffer->backing_store()); | |
910 if (!compiled_module->has_globals_start()) { | |
911 WasmCompiledModule::recreate_globals_start(compiled_module, factory, | |
912 start_address); | |
913 } else { | |
914 compiled_module->set_globals_start(start_address); | |
915 } | |
916 } | |
917 | |
783 MaybeHandle<String> WasmCompiledModule::ExtractUtf8StringFromModuleBytes( | 918 MaybeHandle<String> WasmCompiledModule::ExtractUtf8StringFromModuleBytes( |
784 Isolate* isolate, Handle<WasmCompiledModule> compiled_module, | 919 Isolate* isolate, Handle<WasmCompiledModule> compiled_module, |
785 uint32_t offset, uint32_t size) { | 920 uint32_t offset, uint32_t size) { |
786 // TODO(wasm): cache strings from modules if it's a performance win. | 921 // TODO(wasm): cache strings from modules if it's a performance win. |
787 Handle<SeqOneByteString> module_bytes(compiled_module->module_bytes(), | 922 Handle<SeqOneByteString> module_bytes(compiled_module->module_bytes(), |
788 isolate); | 923 isolate); |
789 DCHECK_GE(module_bytes->length(), offset); | 924 DCHECK_GE(module_bytes->length(), offset); |
790 DCHECK_GE(module_bytes->length() - offset, size); | 925 DCHECK_GE(module_bytes->length() - offset, size); |
791 Address raw = module_bytes->GetCharsAddress() + offset; | 926 Address raw = module_bytes->GetCharsAddress() + offset; |
792 if (!unibrow::Utf8::Validate(reinterpret_cast<const byte*>(raw), size)) | 927 if (!unibrow::Utf8::Validate(reinterpret_cast<const byte*>(raw), size)) |
(...skipping 12 matching lines...) Expand all Loading... | |
805 #define WCM_CHECK_TYPE(NAME, TYPE_CHECK) \ | 940 #define WCM_CHECK_TYPE(NAME, TYPE_CHECK) \ |
806 do { \ | 941 do { \ |
807 Object* obj = arr->get(kID_##NAME); \ | 942 Object* obj = arr->get(kID_##NAME); \ |
808 if (!(TYPE_CHECK)) return false; \ | 943 if (!(TYPE_CHECK)) return false; \ |
809 } while (false); | 944 } while (false); |
810 #define WCM_CHECK_OBJECT(TYPE, NAME) \ | 945 #define WCM_CHECK_OBJECT(TYPE, NAME) \ |
811 WCM_CHECK_TYPE(NAME, obj->IsUndefined(isolate) || obj->Is##TYPE()) | 946 WCM_CHECK_TYPE(NAME, obj->IsUndefined(isolate) || obj->Is##TYPE()) |
812 #define WCM_CHECK_WASM_OBJECT(TYPE, NAME) \ | 947 #define WCM_CHECK_WASM_OBJECT(TYPE, NAME) \ |
813 WCM_CHECK_TYPE(NAME, TYPE::Is##TYPE(obj)) | 948 WCM_CHECK_TYPE(NAME, TYPE::Is##TYPE(obj)) |
814 #define WCM_CHECK_WEAK_LINK(TYPE, NAME) WCM_CHECK_OBJECT(WeakCell, NAME) | 949 #define WCM_CHECK_WEAK_LINK(TYPE, NAME) WCM_CHECK_OBJECT(WeakCell, NAME) |
815 #define WCM_CHECK_SMALL_NUMBER(TYPE, NAME) WCM_CHECK_TYPE(NAME, obj->IsSmi()) | 950 #define WCM_CHECK_SMALL_NUMBER(TYPE, NAME) \ |
951 WCM_CHECK_TYPE(NAME, obj->IsUndefined(isolate) || obj->IsSmi()) | |
bradnelson
2017/03/29 20:49:07
Maybe worth comments on why this and the one below
Mircea Trofin
2017/03/29 20:56:30
Done.
| |
816 #define WCM_CHECK(KIND, TYPE, NAME) WCM_CHECK_##KIND(TYPE, NAME) | 952 #define WCM_CHECK(KIND, TYPE, NAME) WCM_CHECK_##KIND(TYPE, NAME) |
953 #define WCM_CHECK_SMALL_FIXED_NUMBER(TYPE, NAME) \ | |
954 WCM_CHECK_TYPE(NAME, obj->IsSmi()) | |
955 #define WCM_CHECK_LARGE_NUMBER(TYPE, NAME) \ | |
956 WCM_CHECK_TYPE(NAME, obj->IsUndefined(isolate) || obj->IsMutableHeapNumber()) | |
817 WCM_PROPERTY_TABLE(WCM_CHECK) | 957 WCM_PROPERTY_TABLE(WCM_CHECK) |
818 #undef WCM_CHECK | 958 #undef WCM_CHECK |
819 | 959 |
820 // All checks passed. | 960 // All checks passed. |
821 return true; | 961 return true; |
822 } | 962 } |
823 | 963 |
824 void WasmCompiledModule::PrintInstancesChain() { | 964 void WasmCompiledModule::PrintInstancesChain() { |
825 #if DEBUG | 965 #if DEBUG |
826 if (!FLAG_trace_wasm_instances) return; | 966 if (!FLAG_trace_wasm_instances) return; |
(...skipping 11 matching lines...) Expand all Loading... | |
838 void WasmCompiledModule::ReinitializeAfterDeserialization( | 978 void WasmCompiledModule::ReinitializeAfterDeserialization( |
839 Isolate* isolate, Handle<WasmCompiledModule> compiled_module) { | 979 Isolate* isolate, Handle<WasmCompiledModule> compiled_module) { |
840 // This method must only be called immediately after deserialization. | 980 // This method must only be called immediately after deserialization. |
841 // At this point, no module wrapper exists, so the shared module data is | 981 // At this point, no module wrapper exists, so the shared module data is |
842 // incomplete. | 982 // incomplete. |
843 Handle<WasmSharedModuleData> shared( | 983 Handle<WasmSharedModuleData> shared( |
844 static_cast<WasmSharedModuleData*>(compiled_module->get(kID_shared)), | 984 static_cast<WasmSharedModuleData*>(compiled_module->get(kID_shared)), |
845 isolate); | 985 isolate); |
846 DCHECK(!WasmSharedModuleData::IsWasmSharedModuleData(*shared)); | 986 DCHECK(!WasmSharedModuleData::IsWasmSharedModuleData(*shared)); |
847 WasmSharedModuleData::ReinitializeAfterDeserialization(isolate, shared); | 987 WasmSharedModuleData::ReinitializeAfterDeserialization(isolate, shared); |
988 WasmCompiledModule::Reset(isolate, *compiled_module); | |
848 DCHECK(WasmSharedModuleData::IsWasmSharedModuleData(*shared)); | 989 DCHECK(WasmSharedModuleData::IsWasmSharedModuleData(*shared)); |
849 } | 990 } |
850 | 991 |
851 uint32_t WasmCompiledModule::mem_size() const { | 992 uint32_t WasmCompiledModule::mem_size() const { |
852 return has_memory() ? memory()->byte_length()->Number() : default_mem_size(); | 993 DCHECK(has_embedded_mem_size() == has_embedded_mem_start()); |
994 return has_embedded_mem_start() ? embedded_mem_size() : default_mem_size(); | |
853 } | 995 } |
854 | 996 |
855 uint32_t WasmCompiledModule::default_mem_size() const { | 997 uint32_t WasmCompiledModule::default_mem_size() const { |
856 return min_mem_pages() * WasmModule::kPageSize; | 998 return min_mem_pages() * WasmModule::kPageSize; |
857 } | 999 } |
858 | 1000 |
859 MaybeHandle<String> WasmCompiledModule::GetFunctionNameOrNull( | 1001 MaybeHandle<String> WasmCompiledModule::GetFunctionNameOrNull( |
860 Isolate* isolate, Handle<WasmCompiledModule> compiled_module, | 1002 Isolate* isolate, Handle<WasmCompiledModule> compiled_module, |
861 uint32_t func_index) { | 1003 uint32_t func_index) { |
862 DCHECK_LT(func_index, compiled_module->module()->functions.size()); | 1004 DCHECK_LT(func_index, compiled_module->module()->functions.size()); |
(...skipping 351 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1214 if (!array->get(kWrapperInstanceObject)->IsWeakCell()) return false; | 1356 if (!array->get(kWrapperInstanceObject)->IsWeakCell()) return false; |
1215 Isolate* isolate = array->GetIsolate(); | 1357 Isolate* isolate = array->GetIsolate(); |
1216 if (!array->get(kNextInstanceWrapper)->IsUndefined(isolate) && | 1358 if (!array->get(kNextInstanceWrapper)->IsUndefined(isolate) && |
1217 !array->get(kNextInstanceWrapper)->IsFixedArray()) | 1359 !array->get(kNextInstanceWrapper)->IsFixedArray()) |
1218 return false; | 1360 return false; |
1219 if (!array->get(kPreviousInstanceWrapper)->IsUndefined(isolate) && | 1361 if (!array->get(kPreviousInstanceWrapper)->IsUndefined(isolate) && |
1220 !array->get(kPreviousInstanceWrapper)->IsFixedArray()) | 1362 !array->get(kPreviousInstanceWrapper)->IsFixedArray()) |
1221 return false; | 1363 return false; |
1222 return true; | 1364 return true; |
1223 } | 1365 } |
OLD | NEW |