Chromium Code Reviews| 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 |