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

Side by Side Diff: runtime/wasm-runtime.cpp

Issue 1918213003: Subzero, Wasm: Dynamically reallocate read buffer. Runtime improvements. (Closed) Base URL: https://chromium.googlesource.com/native_client/pnacl-subzero.git@master
Patch Set: General improvements Created 4 years, 7 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
« no previous file with comments | « pydir/wasm-run-torture-tests.py ('k') | src/IceCompiler.cpp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 //===- subzero/runtime/wasm-runtime.cpp - Subzero WASM runtime source -----===// 1 //===- subzero/runtime/wasm-runtime.cpp - Subzero WASM runtime source -----===//
2 // 2 //
3 // The Subzero Code Generator 3 // The Subzero Code Generator
4 // 4 //
5 // This file is distributed under the University of Illinois Open Source 5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details. 6 // License. See LICENSE.TXT for details.
7 // 7 //
8 //===----------------------------------------------------------------------===// 8 //===----------------------------------------------------------------------===//
9 // 9 //
10 // This file implements the system calls required by the libc that is included 10 // This file implements the system calls required by the libc that is included
11 // in WebAssembly programs. 11 // in WebAssembly programs.
12 // 12 //
13 //===----------------------------------------------------------------------===// 13 //===----------------------------------------------------------------------===//
14 14
15 #include <cassert> 15 #include <cassert>
16 #include <cmath> 16 #include <cmath>
17 // TODO (eholk): change to cstdint 17 #include <errno.h>
18 #include <fcntl.h>
19 #include <iostream>
20 #include <math.h>
18 #include <stdint.h> 21 #include <stdint.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <sys/ioctl.h>
26 #include <sys/types.h>
27 #include <sys/stat.h>
28 #include <termios.h>
29 #include <time.h>
30 #include <unistd.h>
31
32 #ifdef WASM_TRACE_RUNTIME
33 #define TRACE_ENTRY() \
34 { std::cerr << __func__ << "(...) = "; }
35 template <typename T> T trace(T x) {
36 std::cerr << x << std::endl;
37 return x;
38 }
39 void trace() { std::cerr << "(void)" << std::endl; }
40 #else
41 #define TRACE_ENTRY()
42 template <typename T> T trace(T x) { return x; }
43 void trace() {}
44 #endif // WASM_TRACE_RUNTIME
45
46 extern "C" {
47 extern char WASM_MEMORY[];
48 extern uint32_t WASM_DATA_SIZE;
49 extern uint32_t WASM_NUM_PAGES;
50 } // end of extern "C"
19 51
20 namespace { 52 namespace {
21 uint32_t HeapBreak; 53 uint32_t HeapBreak;
22 54
23 // TODO (eholk): make all of these constexpr. 55 // TODO (eholk): make all of these constexpr.
24 const uint32_t PageSizeLog2 = 16; 56 const uint32_t PageSizeLog2 = 16;
25 const uint32_t PageSize = 1 << PageSizeLog2; // 64KB 57 const uint32_t PageSize = 1 << PageSizeLog2; // 64KB
26 const uint32_t StackPtrLoc = 1024; // defined by emscripten 58 const uint32_t StackPtrLoc = 1024; // defined by emscripten
27 59
28 uint32_t pageNum(uint32_t Index) { return Index >> PageSizeLog2; } 60 uint32_t pageNum(uint32_t Index) { return Index >> PageSizeLog2; }
29 } // end of anonymous namespace 61 } // end of anonymous namespace
30 62
31 namespace env { 63 namespace env {
32 double floor(double X) { return std::floor(X); } 64 double floor(double X) { return std::floor(X); }
33 65
34 float floor(float X) { return std::floor(X); } 66 float floor(float X) { return std::floor(X); }
35 } // end of namespace env 67 } // end of namespace env
36 68
37 // TODO (eholk): move the C parts outside and use C++ name mangling. 69 // TODO (eholk): move the C parts outside and use C++ name mangling.
70
71 namespace {
72
73 /// Some runtime functions need to return pointers. The WasmData struct is used
74 /// to preallocate space for these on the heap.
75 struct WasmData {
76
77 /// StrBuf is returned by functions that return strings.
78 char StrBuf[256];
79 };
80
81 WasmData *GlobalData = NULL;
82
83 int toWasm(void *Ptr) {
84 return reinterpret_cast<int>(reinterpret_cast<char *>(Ptr) - WASM_MEMORY);
85 }
86
87 template <typename T> T *wasmPtr(int Index) {
88 if (pageNum(Index) < WASM_NUM_PAGES) {
89 return reinterpret_cast<T *>(WASM_MEMORY + Index);
90 }
91 abort();
92 }
93
94 template <typename T> class WasmPtr {
95 int Ptr;
96
97 public:
98 WasmPtr(int Ptr) : Ptr(Ptr) {
99 // TODO (eholk): make this a static_assert once we have C++11
100 assert(sizeof(*this) == sizeof(int));
101 }
102
103 WasmPtr(T *Ptr) : Ptr(toWasm(Ptr)) {}
104
105 T &operator*() const { return *asPtr(); }
106
107 T *asPtr() const { return wasmPtr<T>(Ptr); }
108
109 int asInt() const { return Ptr; }
110 };
111
112 template <typename T> class WasmArray {
113 int Ptr;
114
115 public:
116 WasmArray(int Ptr) : Ptr(Ptr) {
117 // TODO (eholk): make this a static_assert once we have C++11.
118 assert(sizeof(*this) == sizeof(int));
119 }
120
121 T &operator[](unsigned int Index) const { return wasmPtr<T>(Ptr)[Index]; }
122 };
123 } // end of anonymous namespace
124
125 // TODO (eholk): move the C parts outside and use C++ name mangling.
38 extern "C" { 126 extern "C" {
39 #include <errno.h>
40 #include <fcntl.h>
41 #include <math.h>
42 #include <stdio.h>
43 #include <stdlib.h>
44 #include <string.h>
45 #include <sys/types.h>
46 #include <sys/stat.h>
47 #include <unistd.h>
48 127
49 extern char WASM_MEMORY[]; 128 void __Sz_bounds_fail() {
50 extern uint32_t WASM_DATA_SIZE; 129 std::cerr << "Bounds check failure" << std::endl;
51 extern uint32_t WASM_NUM_PAGES; 130 abort();
131 }
132
133 void __Sz_indirect_fail() {
134 std::cerr << "Invalid indirect call target" << std::endl;
135 abort();
136 }
52 137
53 void env$$abort() { 138 void env$$abort() {
54 fprintf(stderr, "Aborting...\n"); 139 fprintf(stderr, "Aborting...\n");
55 abort(); 140 abort();
56 } 141 }
57 142
58 void env$$_abort() { env$$abort(); } 143 void env$$_abort() { env$$abort(); }
59 144
60 double env$$floor_f(float X) { return env::floor(X); } 145 double env$$floor_f(float X) {
61 double env$$floor_d(double X) { return env::floor(X); } 146 TRACE_ENTRY();
147 return env::floor(X);
148 }
149 double env$$floor_d(double X) {
150 TRACE_ENTRY();
151 return env::floor(X);
152 }
62 153
63 void env$$exit(int Status) { exit(Status); } 154 void env$$exit(int Status) {
64 void env$$_exit(int Status) { env$$exit(Status); } 155 TRACE_ENTRY();
156 exit(Status);
157 }
158 void env$$_exit(int Status) {
159 TRACE_ENTRY();
160 env$$exit(Status);
161 }
65 162
66 #define UNIMPLEMENTED(f) \ 163 #define UNIMPLEMENTED(f) \
67 void env$$##f() { \ 164 void env$$##f() { \
68 fprintf(stderr, "Unimplemented: " #f "\n"); \ 165 fprintf(stderr, "Unimplemented: " #f "\n"); \
69 abort(); \ 166 abort(); \
70 } 167 }
71 168
72 int32_t env$$sbrk(int32_t Increment) { 169 int32_t env$$sbrk(int32_t Increment) {
170 TRACE_ENTRY();
171 uint32_t OldBreak = HeapBreak;
73 HeapBreak += Increment; 172 HeapBreak += Increment;
74 return HeapBreak; 173 return trace(OldBreak);
75 } 174 }
76 175
77 UNIMPLEMENTED(setjmp) 176 UNIMPLEMENTED(__addtf3)
78 UNIMPLEMENTED(longjmp)
79 UNIMPLEMENTED(__assert_fail) 177 UNIMPLEMENTED(__assert_fail)
80 UNIMPLEMENTED(__builtin_malloc) 178 UNIMPLEMENTED(__builtin_apply)
179 UNIMPLEMENTED(__builtin_apply_args)
81 UNIMPLEMENTED(__builtin_isinff) 180 UNIMPLEMENTED(__builtin_isinff)
82 UNIMPLEMENTED(__builtin_isinfl) 181 UNIMPLEMENTED(__builtin_isinfl)
83 UNIMPLEMENTED(__builtin_apply) 182 UNIMPLEMENTED(__builtin_malloc)
84 UNIMPLEMENTED(__builtin_apply_args) 183 UNIMPLEMENTED(__divtf3)
85 UNIMPLEMENTED(pthread_cleanup_push) 184 UNIMPLEMENTED(__eqtf2)
86 UNIMPLEMENTED(pthread_cleanup_pop) 185 UNIMPLEMENTED(__extenddftf2)
87 UNIMPLEMENTED(pthread_self) 186 UNIMPLEMENTED(__extendsftf2)
187 UNIMPLEMENTED(__fixsfti)
188 UNIMPLEMENTED(__fixtfdi)
189 UNIMPLEMENTED(__fixtfsi)
190 UNIMPLEMENTED(__fixunstfsi)
88 UNIMPLEMENTED(__floatditf) 191 UNIMPLEMENTED(__floatditf)
89 UNIMPLEMENTED(__floatsitf) 192 UNIMPLEMENTED(__floatsitf)
90 UNIMPLEMENTED(__fixtfdi) 193 UNIMPLEMENTED(__floatunsitf)
91 UNIMPLEMENTED(__fixtfsi)
92 UNIMPLEMENTED(__fixsfti)
93 UNIMPLEMENTED(__netf2)
94 UNIMPLEMENTED(__getf2) 194 UNIMPLEMENTED(__getf2)
95 UNIMPLEMENTED(__eqtf2) 195 UNIMPLEMENTED(__letf2)
96 UNIMPLEMENTED(__lttf2) 196 UNIMPLEMENTED(__lttf2)
97 UNIMPLEMENTED(__addtf3)
98 UNIMPLEMENTED(__subtf3)
99 UNIMPLEMENTED(__divtf3)
100 UNIMPLEMENTED(__multf3) 197 UNIMPLEMENTED(__multf3)
101 UNIMPLEMENTED(__multi3) 198 UNIMPLEMENTED(__multi3)
102 UNIMPLEMENTED(__lock) 199 UNIMPLEMENTED(__netf2)
103 UNIMPLEMENTED(__unlock) 200 UNIMPLEMENTED(__subtf3)
104 UNIMPLEMENTED(__syscall6) // sys_close
105 UNIMPLEMENTED(__syscall140) // sys_llseek 201 UNIMPLEMENTED(__syscall140) // sys_llseek
202 UNIMPLEMENTED(__syscall221) // sys_fcntl64
203 UNIMPLEMENTED(__trunctfdf2)
204 UNIMPLEMENTED(__trunctfsf2)
106 UNIMPLEMENTED(__unordtf2) 205 UNIMPLEMENTED(__unordtf2)
107 UNIMPLEMENTED(__fixunstfsi) 206 UNIMPLEMENTED(longjmp)
108 UNIMPLEMENTED(__floatunsitf) 207 UNIMPLEMENTED(pthread_cleanup_pop)
109 UNIMPLEMENTED(__extenddftf2) 208 UNIMPLEMENTED(pthread_cleanup_push)
110 209 UNIMPLEMENTED(pthread_self)
111 void *wasmPtr(uint32_t Index) { 210 UNIMPLEMENTED(setjmp)
112 if (pageNum(Index) < WASM_NUM_PAGES) { 211
113 return WASM_MEMORY + Index; 212 // The empty comment is to keep clang-fmt from breaking this pre-C++11 code.
Jim Stichnoth 2016/04/29 20:57:38 lol
114 } 213 extern int __szwasm_main(int, WasmPtr<WasmPtr<char> /**/>);
115 abort(); 214
116 } 215 #define WASM_REF(Type, Index) (WasmPtr<Type>(Index).asPtr())
117
118 extern int __szwasm_main(int, const char **);
119
120 #define WASM_REF(Type, Index) ((Type *)wasmPtr(Index))
121 #define WASM_DEREF(Type, Index) (*WASM_REF(Type, Index)) 216 #define WASM_DEREF(Type, Index) (*WASM_REF(Type, Index))
122 217
123 int main(int argc, const char **argv) { 218 int main(int argc, const char **argv) {
219 // fprintf(stderr, "main(%d)\n", argc);
Jim Stichnoth 2016/04/29 20:57:38 remove?
Eric Holk 2016/04/29 21:42:55 Done.
220
221 // TODO (eholk): align these allocations correctly.
222
223 // Allocate space for the global data.
224 HeapBreak = WASM_DATA_SIZE;
225 GlobalData = WASM_REF(WasmData, HeapBreak);
226 HeapBreak += sizeof(WasmData);
227
228 // copy the command line arguments.
229 // The empty comment is to keep clang-fmt from breaking this pre-C++11 code.
230 WasmPtr<WasmPtr<char> /**/> WasmArgV = HeapBreak;
Jim Stichnoth 2016/04/29 20:57:38 You could also consider making WasmPtr<char> into
Eric Holk 2016/04/29 21:42:55 Good idea. Done.
231 WasmPtr<char> *WasmArgVPtr = WasmArgV.asPtr();
232 HeapBreak += argc * sizeof(*WasmArgVPtr);
233
234 for (int i = 0; i < argc; ++i) {
235 WasmArgVPtr[i] = HeapBreak;
236 strcpy(WASM_REF(char, HeapBreak), argv[i]);
237 HeapBreak += strlen(argv[i]) + 1;
238 }
239
124 // Initialize the break to the nearest page boundary after the data segment 240 // Initialize the break to the nearest page boundary after the data segment
125 HeapBreak = (WASM_DATA_SIZE + PageSize - 1) & ~(PageSize - 1); 241 HeapBreak = (WASM_DATA_SIZE + PageSize - 1) & ~(PageSize - 1);
126 242
127 // Initialize the stack pointer. 243 // Initialize the stack pointer.
128 WASM_DEREF(int32_t, StackPtrLoc) = WASM_NUM_PAGES << PageSizeLog2; 244 WASM_DEREF(int32_t, StackPtrLoc) = WASM_NUM_PAGES << PageSizeLog2;
129 245
130 return __szwasm_main(argc, argv); 246 return __szwasm_main(argc, WasmArgV);
131 } 247 }
132 248
133 int env$$abs(int a) { return abs(a); } 249 int env$$abs(int a) {
134 250 TRACE_ENTRY();
135 double env$$pow(double x, double y) { return pow(x, y); } 251 return trace(abs(a));
252 }
253
254 clock_t env$$clock() {
255 TRACE_ENTRY();
256 return trace(clock());
257 }
258
259 int env$$ctime(WasmPtr<time_t> Time) {
260 TRACE_ENTRY();
261 char *CTime = ctime(Time.asPtr());
262 strncpy(GlobalData->StrBuf, CTime, sizeof(GlobalData->StrBuf));
263 GlobalData->StrBuf[sizeof(GlobalData->StrBuf) - 1] = '\0';
264 return trace(WasmPtr<char>(GlobalData->StrBuf).asInt());
265 }
266
267 double env$$pow(double x, double y) {
268 TRACE_ENTRY();
269 return trace(pow(x, y));
270 }
271
272 time_t env$$time(WasmPtr<time_t> Time) {
273 TRACE_ENTRY();
274 time_t *TimePtr = WASM_REF(time_t, Time);
275 return trace(time(TimePtr));
276 }
277
278 // lock and unlock are no-ops in wasm.js, so we mimic that behavior.
279 void env$$__lock(int32_t _) {
280 TRACE_ENTRY();
281 (void)_;
Jim Stichnoth 2016/04/29 20:57:38 Can you just omit the argument name in the declara
Eric Holk 2016/04/29 21:42:55 Ah, that seems to work. I seem to remember that no
282 trace();
283 }
284
285 void env$$__unlock(int32_t _) {
286 TRACE_ENTRY();
287 (void)_;
288 trace();
289 }
290
291 /// sys_read
292 int env$$__syscall3(int Which, WasmArray<int> VarArgs) {
293 TRACE_ENTRY();
294 int Fd = VarArgs[0];
295 int Buffer = VarArgs[1];
296 int Length = VarArgs[2];
297
298 return trace(read(Fd, WASM_REF(char *, Buffer), Length));
299 }
136 300
137 /// sys_write 301 /// sys_write
138 int env$$__syscall4(int Which, int VarArgs) { 302 int env$$__syscall4(int Which, WasmArray<int> VarArgs) {
139 int Fd = WASM_DEREF(int, VarArgs + 0 * sizeof(int)); 303 TRACE_ENTRY();
140 int Buffer = WASM_DEREF(int, VarArgs + 1 * sizeof(int)); 304 int Fd = VarArgs[0];
141 int Length = WASM_DEREF(int, VarArgs + 2 * sizeof(int)); 305 int Buffer = VarArgs[1];
142 306 int Length = VarArgs[2];
143 return write(Fd, WASM_REF(char *, Buffer), Length); 307
308 return trace(write(Fd, WASM_REF(char *, Buffer), Length));
144 } 309 }
145 310
146 /// sys_open 311 /// sys_open
147 int env$$__syscall5(int Which, int VarArgs) { 312 int env$$__syscall5(int Which, WasmArray<int> VarArgs) {
148 int WasmPath = WASM_DEREF(int, VarArgs); 313 TRACE_ENTRY();
149 int Flags = WASM_DEREF(int, VarArgs + 4); 314 int WasmPath = VarArgs[0];
150 int Mode = WASM_DEREF(int, VarArgs + 8); 315 int Flags = VarArgs[1];
316 int Mode = VarArgs[2];
151 const char *Path = WASM_REF(char, WasmPath); 317 const char *Path = WASM_REF(char, WasmPath);
152 318
153 fprintf(stderr, "sys_open(%s, %d, %d)\n", Path, Flags, Mode); 319 return trace(open(Path, Flags, Mode));
154 320 }
155 return open(Path, Flags, Mode); 321
322 /// sys_close
323 int env$$__syscall6(int Which, WasmArray<int> VarArgs) {
324 TRACE_ENTRY();
325 int Fd = VarArgs[0];
326
327 return trace(close(Fd));
328 }
329
330 /// sys_unlink
331 int env$$__syscall10(int Which, WasmArray<int> VarArgs) {
332 TRACE_ENTRY();
333 int WasmPath = VarArgs[0];
334 const char *Path = WASM_REF(char, WasmPath);
335
336 return trace(unlink(Path));
156 } 337 }
157 338
158 /// sys_getpid 339 /// sys_getpid
159 int env$$__syscall20(int Which, int VarArgs) { 340 int env$$__syscall20(int Which, WasmArray<int> VarArgs) {
341 TRACE_ENTRY();
160 (void)Which; 342 (void)Which;
161 (void)VarArgs; 343 (void)VarArgs;
162 344
163 return getpid(); 345 return trace(getpid());
346 }
347
348 /// sys_rmdir
349 int env$$__syscall40(int Which, WasmArray<int> VarArgs) {
350 TRACE_ENTRY();
351 int WasmPath = VarArgs[0];
352 const char *Path = WASM_REF(char, WasmPath);
353
354 return trace(rmdir(Path));
164 } 355 }
165 356
166 /// sys_ioctl 357 /// sys_ioctl
167 int env$$__syscall54(int A, int B) { 358 int env$$__syscall54(int Which, WasmArray<int> VarArgs) {
168 int Fd = WASM_DEREF(int, B + 0 * sizeof(int)); 359 TRACE_ENTRY();
169 int Op = WASM_DEREF(int, B + 1 * sizeof(int)); 360 int Fd = VarArgs[0];
170 int ArgP = WASM_DEREF(int, B + 2 * sizeof(int)); 361 int Op = VarArgs[1];
171 // TODO (eholk): implement sys_ioctl 362 int ArgP = VarArgs[2];
172 return -ENOTTY; 363
173 } 364 switch (Op) {
174 365 case TCGETS: {
175 /// sys_write 366 // struct termios has no pointers. Otherwise, we'd have to rewrite them.
176 int env$$__syscall146(int Which, int VarArgs) { 367 struct termios *TermIOS = WASM_REF(struct termios, ArgP);
177 368 return trace(ioctl(Fd, TCGETS, TermIOS));
178 int Fd = WASM_DEREF(int, VarArgs); 369 }
179 int Iov = WASM_DEREF(int, VarArgs + sizeof(int)); 370 default:
180 int Iovcnt = WASM_DEREF(int, VarArgs + 2 * sizeof(int)); 371 // TODO (eholk): implement more ioctls
372 return trace(-ENOTTY);
373 }
374 }
375
376 struct IoVec {
377 WasmPtr<char> Ptr;
378 int Length;
379 };
380
381 /// sys_readv
382 int env$$__syscall145(int Which, WasmArray<int> VarArgs) {
383 TRACE_ENTRY();
384 int Fd = VarArgs[0];
385 WasmArray<IoVec> Iov = VarArgs[1];
386 int Iovcnt = VarArgs[2];
181 387
182 int Count = 0; 388 int Count = 0;
183 389
184 for (int I = 0; I < Iovcnt; ++I) { 390 for (int I = 0; I < Iovcnt; ++I) {
185 void *Ptr = WASM_REF(void, WASM_DEREF(int, Iov + I * 8)); 391 int Curr = read(Fd, Iov[I].Ptr.asPtr(), Iov[I].Length);
186 int Length = WASM_DEREF(int, Iov + I * 8 + 4);
187
188 int Curr = write(Fd, Ptr, Length);
189 392
190 if (Curr < 0) { 393 if (Curr < 0) {
191 return -1; 394 return trace(-1);
192 } 395 }
193 Count += Curr; 396 Count += Curr;
194 } 397 }
195 return Count; 398 return trace(Count);
399 }
400
401 /// sys_writev
402 int env$$__syscall146(int Which, WasmArray<int> VarArgs) {
403 TRACE_ENTRY();
404 int Fd = VarArgs[0];
405 WasmArray<IoVec> Iov = VarArgs[1];
406 int Iovcnt = VarArgs[2];
407
408 int Count = 0;
409
410 for (int I = 0; I < Iovcnt; ++I) {
411 int Curr = write(Fd, Iov[I].Ptr.asPtr(), Iov[I].Length);
412
413 if (Curr < 0) {
414 return trace(-1);
415 }
416 Count += Curr;
417 }
418 return trace(Count);
196 } 419 }
197 420
198 /// sys_mmap_pgoff 421 /// sys_mmap_pgoff
199 int env$$__syscall192(int Which, int VarArgs) { 422 int env$$__syscall192(int Which, WasmArray<int> VarArgs) {
423 TRACE_ENTRY();
200 (void)Which; 424 (void)Which;
201 (void)VarArgs; 425 (void)VarArgs;
202 426
203 // TODO (eholk): figure out how to implement this. 427 // TODO (eholk): figure out how to implement this.
204 428
205 return -ENOMEM; 429 return trace(-ENOMEM);
206 } 430 }
207 } // end of extern "C" 431 } // end of extern "C"
OLDNEW
« no previous file with comments | « pydir/wasm-run-torture-tests.py ('k') | src/IceCompiler.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698