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

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

Powered by Google App Engine
This is Rietveld 408576698