js/src/jit/AsmJS.h

branch
TOR_BUG_3246
changeset 7
129ffea94266
equal deleted inserted replaced
-1:000000000000 0:1d35d1e0e30d
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2 * vim: set ts=8 sts=4 et sw=4 tw=99:
3 * This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6
7 #ifndef jit_AsmJS_h
8 #define jit_AsmJS_h
9
10 #include <stddef.h>
11
12 #include "js/TypeDecls.h"
13 #include "vm/ObjectImpl.h"
14
15 namespace js {
16
17 class ExclusiveContext;
18 namespace frontend {
19 template <typename ParseHandler> struct Parser;
20 template <typename ParseHandler> struct ParseContext;
21 class FullParseHandler;
22 struct ParseNode;
23 }
24
25 typedef frontend::Parser<frontend::FullParseHandler> AsmJSParser;
26 typedef frontend::ParseContext<frontend::FullParseHandler> AsmJSParseContext;
27
28 // Takes over parsing of a function starting with "use asm". The return value
29 // indicates whether an error was reported which the caller should propagate.
30 // If no error was reported, the function may still fail to validate as asm.js.
31 // In this case, the parser.tokenStream has been advanced an indeterminate
32 // amount and the entire function should be reparsed from the beginning.
33 extern bool
34 CompileAsmJS(ExclusiveContext *cx, AsmJSParser &parser, frontend::ParseNode *stmtList,
35 bool *validated);
36
37 // The assumed page size; dynamically checked in CompileAsmJS.
38 const size_t AsmJSPageSize = 4096;
39
40 // The asm.js spec requires that the ArrayBuffer's byteLength be a multiple of 4096.
41 static const size_t AsmJSAllocationGranularity = 4096;
42
43 #ifdef JS_CODEGEN_X64
44 // On x64, the internal ArrayBuffer data array is inflated to 4GiB (only the
45 // byteLength portion of which is accessible) so that out-of-bounds accesses
46 // (made using a uint32 index) are guaranteed to raise a SIGSEGV.
47 static const size_t AsmJSBufferProtectedSize = 4 * 1024ULL * 1024ULL * 1024ULL;
48
49 // To avoid dynamically checking bounds on each load/store, asm.js code relies
50 // on the SIGSEGV handler in AsmJSSignalHandlers.cpp. However, this only works
51 // if we can guarantee that *any* out-of-bounds access generates a fault. This
52 // isn't generally true since an out-of-bounds access could land on other
53 // Mozilla data. To overcome this on x64, we reserve an entire 4GB space,
54 // making only the range [0, byteLength) accessible, and use a 32-bit unsigned
55 // index into this space. (x86 and ARM require different tricks.)
56 //
57 // One complication is that we need to put an ObjectElements struct immediately
58 // before the data array (as required by the general JSObject data structure).
59 // Thus, we must stick a page before the elements to hold ObjectElements.
60 //
61 // |<------------------------------ 4GB + 1 pages --------------------->|
62 // |<--- sizeof --->|<------------------- 4GB ----------------->|
63 //
64 // | waste | ObjectElements | data array | inaccessible reserved memory |
65 // ^ ^ ^
66 // | \ /
67 // obj->elements required to be page boundaries
68 //
69 static const size_t AsmJSMappedSize = AsmJSPageSize + AsmJSBufferProtectedSize;
70 #endif // JS_CODEGEN_X64
71
72 #ifdef JS_ION
73
74 // Return whether asm.js optimization is inhibitted by the platform or
75 // dynamically disabled:
76 extern bool
77 IsAsmJSCompilationAvailable(JSContext *cx, unsigned argc, JS::Value *vp);
78
79 #else // JS_ION
80
81 inline bool
82 IsAsmJSCompilationAvailable(JSContext *cx, unsigned argc, Value *vp)
83 {
84 CallArgs args = CallArgsFromVp(argc, vp);
85 args.rval().set(BooleanValue(false));
86 return true;
87 }
88
89 #endif // JS_ION
90
91 // The Asm.js heap length is constrained by the x64 backend heap access scheme
92 // to be a multiple of the page size which is 4096 bytes, and also constrained
93 // by the limits of ARM backends 'cmp immediate' instruction which supports a
94 // complex range for the immediate argument.
95 //
96 // ARMv7 mode supports the following immediate constants, and the Thumb T2
97 // instruction encoding also supports the subset of immediate constants used.
98 // abcdefgh 00000000 00000000 00000000
99 // 00abcdef gh000000 00000000 00000000
100 // 0000abcd efgh0000 00000000 00000000
101 // 000000ab cdefgh00 00000000 00000000
102 // 00000000 abcdefgh 00000000 00000000
103 // 00000000 00abcdef gh000000 00000000
104 // 00000000 0000abcd efgh0000 00000000
105 // ...
106 //
107 // The 4096 page size constraint restricts the length to:
108 // xxxxxxxx xxxxxxxx xxxx0000 00000000
109 //
110 // Intersecting all the above constraints gives:
111 // Heap length 0x40000000 to 0xff000000 quanta 0x01000000
112 // Heap length 0x10000000 to 0x3fc00000 quanta 0x00400000
113 // Heap length 0x04000000 to 0x0ff00000 quanta 0x00100000
114 // Heap length 0x01000000 to 0x03fc0000 quanta 0x00040000
115 // Heap length 0x00400000 to 0x00ff0000 quanta 0x00010000
116 // Heap length 0x00100000 to 0x003fc000 quanta 0x00004000
117 // Heap length 0x00001000 to 0x000ff000 quanta 0x00001000
118 //
119 inline uint32_t
120 RoundUpToNextValidAsmJSHeapLength(uint32_t length)
121 {
122 if (length < 0x00001000u) // Minimum length is the pages size of 4096.
123 return 0x1000u;
124 if (length < 0x00100000u) // < 1M quanta 4K
125 return (length + 0x00000fff) & ~0x00000fff;
126 if (length < 0x00400000u) // < 4M quanta 16K
127 return (length + 0x00003fff) & ~0x00003fff;
128 if (length < 0x01000000u) // < 16M quanta 64K
129 return (length + 0x0000ffff) & ~0x0000ffff;
130 if (length < 0x04000000u) // < 64M quanta 256K
131 return (length + 0x0003ffff) & ~0x0003ffff;
132 if (length < 0x10000000u) // < 256M quanta 1M
133 return (length + 0x000fffff) & ~0x000fffff;
134 if (length < 0x40000000u) // < 1024M quanta 4M
135 return (length + 0x003fffff) & ~0x003fffff;
136 // < 4096M quanta 16M. Note zero is returned if over 0xff000000 but such
137 // lengths are not currently valid.
138 JS_ASSERT(length <= 0xff000000);
139 return (length + 0x00ffffff) & ~0x00ffffff;
140 }
141
142 inline bool
143 IsValidAsmJSHeapLength(uint32_t length)
144 {
145 if (length < AsmJSAllocationGranularity)
146 return false;
147 if (length <= 0x00100000u)
148 return (length & 0x00000fff) == 0;
149 if (length <= 0x00400000u)
150 return (length & 0x00003fff) == 0;
151 if (length <= 0x01000000u)
152 return (length & 0x0000ffff) == 0;
153 if (length <= 0x04000000u)
154 return (length & 0x0003ffff) == 0;
155 if (length <= 0x10000000u)
156 return (length & 0x000fffff) == 0;
157 if (length <= 0x40000000u)
158 return (length & 0x003fffff) == 0;
159 if (length <= 0xff000000u)
160 return (length & 0x00ffffff) == 0;
161 return false;
162 }
163
164 } // namespace js
165
166 #endif // jit_AsmJS_h

mercurial