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/macro-assembler.h" | 5 #include "src/macro-assembler.h" |
6 #include "src/objects.h" | 6 #include "src/objects.h" |
7 #include "src/v8.h" | 7 #include "src/v8.h" |
8 | 8 |
9 #include "src/simulator.h" | 9 #include "src/simulator.h" |
10 | 10 |
(...skipping 182 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
193 } | 193 } |
194 if (modified) { | 194 if (modified) { |
195 Assembler::FlushICache(isolate_, code->instruction_start(), | 195 Assembler::FlushICache(isolate_, code->instruction_start(), |
196 code->instruction_size()); | 196 code->instruction_size()); |
197 } | 197 } |
198 } | 198 } |
199 }; | 199 }; |
200 | 200 |
201 namespace { | 201 namespace { |
202 // Internal constants for the layout of the module object. | 202 // Internal constants for the layout of the module object. |
203 const int kWasmModuleInternalFieldCount = 4; | 203 const int kWasmModuleInternalFieldCount = 5; |
204 const int kWasmModuleFunctionTable = 0; | 204 const int kWasmModuleFunctionTable = 0; |
205 const int kWasmModuleCodeTable = 1; | 205 const int kWasmModuleCodeTable = 1; |
206 const int kWasmMemArrayBuffer = 2; | 206 const int kWasmMemArrayBuffer = 2; |
207 const int kWasmGlobalsArrayBuffer = 3; | 207 const int kWasmGlobalsArrayBuffer = 3; |
208 const int kWasmFunctionNamesArray = 4; | |
208 | 209 |
209 size_t AllocateGlobalsOffsets(std::vector<WasmGlobal>& globals) { | 210 size_t AllocateGlobalsOffsets(std::vector<WasmGlobal>& globals) { |
210 uint32_t offset = 0; | 211 uint32_t offset = 0; |
211 if (globals.size() == 0) return 0; | 212 if (globals.size() == 0) return 0; |
212 for (WasmGlobal& global : globals) { | 213 for (WasmGlobal& global : globals) { |
213 byte size = WasmOpcodes::MemSize(global.type); | 214 byte size = WasmOpcodes::MemSize(global.type); |
214 offset = (offset + size - 1) & ~(size - 1); // align | 215 offset = (offset + size - 1) & ~(size - 1); // align |
215 global.offset = offset; | 216 global.offset = offset; |
216 offset += size; | 217 offset += size; |
217 } | 218 } |
(...skipping 21 matching lines...) Expand all Loading... | |
239 } | 240 } |
240 int table_size = static_cast<int>(module->function_table.size()); | 241 int table_size = static_cast<int>(module->function_table.size()); |
241 Handle<FixedArray> fixed = isolate->factory()->NewFixedArray(2 * table_size); | 242 Handle<FixedArray> fixed = isolate->factory()->NewFixedArray(2 * table_size); |
242 for (int i = 0; i < table_size; i++) { | 243 for (int i = 0; i < table_size; i++) { |
243 WasmFunction* function = &module->functions[module->function_table[i]]; | 244 WasmFunction* function = &module->functions[module->function_table[i]]; |
244 fixed->set(i, Smi::FromInt(function->sig_index)); | 245 fixed->set(i, Smi::FromInt(function->sig_index)); |
245 } | 246 } |
246 return fixed; | 247 return fixed; |
247 } | 248 } |
248 | 249 |
250 // Build an array with all function names. If there are N functions in the | |
251 // module, then the first (kIntSize * (N+1)) bytes are integer entries. | |
252 // The first integer entry encodes the number of functions in the module. | |
253 // The entries 1 to N contain offsets into the seconds part of this array. | |
titzer
2016/04/22 13:21:08
s/seconds/second/
| |
254 // After these N+1 integer entries, the second part begins, which holds a | |
255 // concatenation of all function names. If a function is unnamed (not to be | |
256 // confused with an empty name), then the corresponding integer entry contains | |
257 // the negative distance to the next entry with a name. It points behind the | |
258 // last integer entry if there are no more entries with names. | |
259 // This allows to easily determine for each function the start of the next | |
260 // function name, and hence the length of the function name. | |
261 Handle<Object> BuildFunctionNamesArray(Isolate* isolate, WasmModule* module) { | |
titzer
2016/04/22 13:21:08
Can we factor out the encoding and decoding logic
Clemens Hammacher
2016/04/22 14:38:40
OK, will work on that on Monday and then update th
| |
262 uint64_t func_names_length = 0; | |
263 for (auto& func : module->functions) func_names_length += func.name_length; | |
264 int num_funcs_int = static_cast<int>(module->functions.size()); | |
265 int current_offset = (num_funcs_int + 1) * kIntSize; | |
266 uint64_t total_array_length = current_offset + func_names_length; | |
267 int total_array_length_int = static_cast<int>(total_array_length); | |
268 // Check for overflow. Just skip function names if it happens. | |
269 if (total_array_length_int != total_array_length || num_funcs_int < 0 || | |
270 num_funcs_int != module->functions.size()) | |
271 return isolate->factory()->undefined_value(); | |
272 Handle<ByteArray> func_names_arr = | |
273 isolate->factory()->NewByteArray(total_array_length_int, TENURED); | |
274 func_names_arr->set_int(0, num_funcs_int); | |
275 for (int func_index = 0; func_index != num_funcs_int; ++func_index) { | |
titzer
2016/04/22 13:21:08
Would prefer a C++ foreach-loop with a separate in
Clemens Hammacher
2016/04/22 14:38:40
C++ foreach does not work, since we increase func_
| |
276 WasmName name = module->GetNameOrNull(&module->functions[func_index]); | |
277 if (name.name == nullptr) { | |
278 // Find next function with a name, and store the negative distance to that | |
279 // function. On the way, we also set all the entries inbetween. | |
280 int next_func_with_name = func_index + 1; | |
281 while ( | |
282 next_func_with_name != num_funcs_int && | |
283 module->GetNameOrNull(&module->functions[next_func_with_name]).name == | |
284 nullptr) | |
285 ++next_func_with_name; | |
286 for (; func_index < next_func_with_name; ++func_index) | |
287 func_names_arr->set_int(func_index + 1, | |
288 func_index - next_func_with_name); | |
289 --func_index; | |
290 } else { | |
291 func_names_arr->set(current_offset, | |
292 reinterpret_cast<const byte*>(name.name), | |
293 name.length); | |
294 func_names_arr->set_int(func_index + 1, current_offset); | |
295 current_offset += name.length; | |
296 } | |
297 } | |
298 return func_names_arr; | |
299 } | |
300 | |
249 Handle<JSArrayBuffer> NewArrayBuffer(Isolate* isolate, size_t size, | 301 Handle<JSArrayBuffer> NewArrayBuffer(Isolate* isolate, size_t size, |
250 byte** backing_store) { | 302 byte** backing_store) { |
251 if (size > (WasmModule::kMaxMemPages * WasmModule::kPageSize)) { | 303 if (size > (WasmModule::kMaxMemPages * WasmModule::kPageSize)) { |
252 // TODO(titzer): lift restriction on maximum memory allocated here. | 304 // TODO(titzer): lift restriction on maximum memory allocated here. |
253 *backing_store = nullptr; | 305 *backing_store = nullptr; |
254 return Handle<JSArrayBuffer>::null(); | 306 return Handle<JSArrayBuffer>::null(); |
255 } | 307 } |
256 void* memory = | 308 void* memory = |
257 isolate->array_buffer_allocator()->Allocate(static_cast<int>(size)); | 309 isolate->array_buffer_allocator()->Allocate(static_cast<int>(size)); |
258 if (!memory) { | 310 if (!memory) { |
(...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
408 HistogramTimerScope wasm_instantiate_module_time_scope( | 460 HistogramTimerScope wasm_instantiate_module_time_scope( |
409 isolate->counters()->wasm_instantiate_module_time()); | 461 isolate->counters()->wasm_instantiate_module_time()); |
410 this->shared_isolate = isolate; // TODO(titzer): have a real shared isolate. | 462 this->shared_isolate = isolate; // TODO(titzer): have a real shared isolate. |
411 ErrorThrower thrower(isolate, "WasmModule::Instantiate()"); | 463 ErrorThrower thrower(isolate, "WasmModule::Instantiate()"); |
412 Factory* factory = isolate->factory(); | 464 Factory* factory = isolate->factory(); |
413 | 465 |
414 //------------------------------------------------------------------------- | 466 //------------------------------------------------------------------------- |
415 // Allocate the instance and its JS counterpart. | 467 // Allocate the instance and its JS counterpart. |
416 //------------------------------------------------------------------------- | 468 //------------------------------------------------------------------------- |
417 Handle<Map> map = factory->NewMap( | 469 Handle<Map> map = factory->NewMap( |
418 JS_OBJECT_TYPE, | 470 JS_WASM_TYPE, |
419 JSObject::kHeaderSize + kWasmModuleInternalFieldCount * kPointerSize); | 471 JSObject::kHeaderSize + kWasmModuleInternalFieldCount * kPointerSize); |
420 WasmModuleInstance instance(this); | 472 WasmModuleInstance instance(this); |
421 instance.context = isolate->native_context(); | 473 instance.context = isolate->native_context(); |
422 instance.js_object = factory->NewJSObjectFromMap(map, TENURED); | 474 instance.js_object = factory->NewJSObjectFromMap(map, TENURED); |
423 Handle<FixedArray> code_table = | 475 Handle<FixedArray> code_table = |
424 factory->NewFixedArray(static_cast<int>(functions.size()), TENURED); | 476 factory->NewFixedArray(static_cast<int>(functions.size()), TENURED); |
425 instance.js_object->SetInternalField(kWasmModuleCodeTable, *code_table); | 477 instance.js_object->SetInternalField(kWasmModuleCodeTable, *code_table); |
426 | 478 |
427 //------------------------------------------------------------------------- | 479 //------------------------------------------------------------------------- |
428 // Allocate and initialize the linear memory. | 480 // Allocate and initialize the linear memory. |
(...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
575 | 627 |
576 if (mem_export) { | 628 if (mem_export) { |
577 // Export the memory as a named property. | 629 // Export the memory as a named property. |
578 Handle<String> name = factory->InternalizeUtf8String("memory"); | 630 Handle<String> name = factory->InternalizeUtf8String("memory"); |
579 JSObject::AddProperty(exports_object, name, instance.mem_buffer, | 631 JSObject::AddProperty(exports_object, name, instance.mem_buffer, |
580 READ_ONLY); | 632 READ_ONLY); |
581 } | 633 } |
582 } | 634 } |
583 } | 635 } |
584 | 636 |
637 //------------------------------------------------------------------------- | |
638 // Attach an array with function names and an array with offsets into that | |
639 // first array. | |
640 //------------------------------------------------------------------------- | |
641 { | |
642 Handle<Object> arr = BuildFunctionNamesArray(isolate, module_env.module); | |
643 instance.js_object->SetInternalField(kWasmFunctionNamesArray, *arr); | |
644 } | |
645 | |
585 // Run the start function if one was specified. | 646 // Run the start function if one was specified. |
586 if (this->start_function_index >= 0) { | 647 if (this->start_function_index >= 0) { |
587 HandleScope scope(isolate); | 648 HandleScope scope(isolate); |
588 uint32_t index = static_cast<uint32_t>(this->start_function_index); | 649 uint32_t index = static_cast<uint32_t>(this->start_function_index); |
589 Handle<String> name = isolate->factory()->NewStringFromStaticChars("start"); | 650 Handle<String> name = isolate->factory()->NewStringFromStaticChars("start"); |
590 Handle<Code> code = linker.GetFunctionCode(index); | 651 Handle<Code> code = linker.GetFunctionCode(index); |
591 Handle<JSFunction> jsfunc = compiler::CompileJSToWasmWrapper( | 652 Handle<JSFunction> jsfunc = compiler::CompileJSToWasmWrapper( |
592 isolate, &module_env, name, code, instance.js_object, index); | 653 isolate, &module_env, name, code, instance.js_object, index); |
593 | 654 |
594 // Call the JS function. | 655 // Call the JS function. |
(...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
725 Handle<Object> result = retval.ToHandleChecked(); | 786 Handle<Object> result = retval.ToHandleChecked(); |
726 if (result->IsSmi()) { | 787 if (result->IsSmi()) { |
727 return Smi::cast(*result)->value(); | 788 return Smi::cast(*result)->value(); |
728 } | 789 } |
729 if (result->IsHeapNumber()) { | 790 if (result->IsHeapNumber()) { |
730 return static_cast<int32_t>(HeapNumber::cast(*result)->value()); | 791 return static_cast<int32_t>(HeapNumber::cast(*result)->value()); |
731 } | 792 } |
732 thrower.Error("WASM.compileRun() failed: Return value should be number"); | 793 thrower.Error("WASM.compileRun() failed: Return value should be number"); |
733 return -1; | 794 return -1; |
734 } | 795 } |
796 | |
797 Handle<Object> GetWasmFunctionName(Handle<JSObject> wasm, uint32_t func_index) { | |
798 DCHECK(wasm->map()->instance_type() == JS_WASM_TYPE); | |
799 Handle<Object> func_names_arr_obj = handle( | |
800 wasm->GetInternalField(kWasmFunctionNamesArray), wasm->GetIsolate()); | |
801 if (func_names_arr_obj->IsUndefined()) | |
802 return func_names_arr_obj; // Return undefined. | |
803 Handle<ByteArray> func_names_arr = | |
804 Handle<ByteArray>::cast(func_names_arr_obj); | |
805 uint32_t num_funcs = static_cast<uint32_t>(func_names_arr->get_int(0)); | |
806 DCHECK(static_cast<int>(num_funcs) >= 0); | |
807 if (func_index >= num_funcs) | |
808 return wasm->GetIsolate()->factory()->undefined_value(); | |
809 int offset = func_names_arr->get_int(func_index + 1); | |
810 if (offset < 0) return wasm->GetIsolate()->factory()->undefined_value(); | |
811 int next_offset = func_index == num_funcs - 1 | |
812 ? func_names_arr->length() | |
813 : func_names_arr->get_int(func_index + 2); | |
814 if (next_offset < 0) { | |
815 uint32_t next_func_index = func_index + 1 - next_offset; | |
816 next_offset = next_func_index == num_funcs | |
817 ? func_names_arr->length() | |
818 : func_names_arr->get_int(next_func_index + 1); | |
819 } | |
820 DCHECK(next_offset >= 0 && next_offset <= func_names_arr->length()); | |
821 DCHECK(next_offset >= offset); | |
822 ScopedVector<byte> buffer(next_offset - offset); | |
823 func_names_arr->get(offset, buffer.start(), next_offset - offset); | |
824 MaybeHandle<Object> maybe_name = | |
825 wasm->GetIsolate()->factory()->NewStringFromUtf8( | |
826 Vector<const char>::cast(buffer)); | |
827 if (maybe_name.is_null()) | |
828 return wasm->GetIsolate()->factory()->undefined_value(); | |
829 return maybe_name.ToHandleChecked(); | |
830 } | |
831 | |
735 } // namespace wasm | 832 } // namespace wasm |
736 } // namespace internal | 833 } // namespace internal |
737 } // namespace v8 | 834 } // namespace v8 |
OLD | NEW |