Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1021)

Side by Side Diff: src/wasm/wasm-module.cc

Issue 1912103002: [wasm] Store function names in the wasm object (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@wasm-offset-table-2
Patch Set: fix gcmole and signed/unsigned comparison issue Created 4 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« src/objects-inl.h ('K') | « src/wasm/wasm-module.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
OLDNEW
« src/objects-inl.h ('K') | « src/wasm/wasm-module.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698