js/src/jit/AsmJS.h

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/js/src/jit/AsmJS.h	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,166 @@
     1.4 +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
     1.5 + * vim: set ts=8 sts=4 et sw=4 tw=99:
     1.6 + * This Source Code Form is subject to the terms of the Mozilla Public
     1.7 + * License, v. 2.0. If a copy of the MPL was not distributed with this
     1.8 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     1.9 +
    1.10 +#ifndef jit_AsmJS_h
    1.11 +#define jit_AsmJS_h
    1.12 +
    1.13 +#include <stddef.h>
    1.14 +
    1.15 +#include "js/TypeDecls.h"
    1.16 +#include "vm/ObjectImpl.h"
    1.17 +
    1.18 +namespace js {
    1.19 +
    1.20 +class ExclusiveContext;
    1.21 +namespace frontend {
    1.22 +    template <typename ParseHandler> struct Parser;
    1.23 +    template <typename ParseHandler> struct ParseContext;
    1.24 +    class FullParseHandler;
    1.25 +    struct ParseNode;
    1.26 +}
    1.27 +
    1.28 +typedef frontend::Parser<frontend::FullParseHandler> AsmJSParser;
    1.29 +typedef frontend::ParseContext<frontend::FullParseHandler> AsmJSParseContext;
    1.30 +
    1.31 +// Takes over parsing of a function starting with "use asm". The return value
    1.32 +// indicates whether an error was reported which the caller should propagate.
    1.33 +// If no error was reported, the function may still fail to validate as asm.js.
    1.34 +// In this case, the parser.tokenStream has been advanced an indeterminate
    1.35 +// amount and the entire function should be reparsed from the beginning.
    1.36 +extern bool
    1.37 +CompileAsmJS(ExclusiveContext *cx, AsmJSParser &parser, frontend::ParseNode *stmtList,
    1.38 +             bool *validated);
    1.39 +
    1.40 +// The assumed page size; dynamically checked in CompileAsmJS.
    1.41 +const size_t AsmJSPageSize = 4096;
    1.42 +
    1.43 +// The asm.js spec requires that the ArrayBuffer's byteLength be a multiple of 4096.
    1.44 +static const size_t AsmJSAllocationGranularity = 4096;
    1.45 +
    1.46 +#ifdef JS_CODEGEN_X64
    1.47 +// On x64, the internal ArrayBuffer data array is inflated to 4GiB (only the
    1.48 +// byteLength portion of which is accessible) so that out-of-bounds accesses
    1.49 +// (made using a uint32 index) are guaranteed to raise a SIGSEGV.
    1.50 +static const size_t AsmJSBufferProtectedSize = 4 * 1024ULL * 1024ULL * 1024ULL;
    1.51 +
    1.52 +// To avoid dynamically checking bounds on each load/store, asm.js code relies
    1.53 +// on the SIGSEGV handler in AsmJSSignalHandlers.cpp. However, this only works
    1.54 +// if we can guarantee that *any* out-of-bounds access generates a fault. This
    1.55 +// isn't generally true since an out-of-bounds access could land on other
    1.56 +// Mozilla data. To overcome this on x64, we reserve an entire 4GB space,
    1.57 +// making only the range [0, byteLength) accessible, and use a 32-bit unsigned
    1.58 +// index into this space. (x86 and ARM require different tricks.)
    1.59 +//
    1.60 +// One complication is that we need to put an ObjectElements struct immediately
    1.61 +// before the data array (as required by the general JSObject data structure).
    1.62 +// Thus, we must stick a page before the elements to hold ObjectElements.
    1.63 +//
    1.64 +//   |<------------------------------ 4GB + 1 pages --------------------->|
    1.65 +//           |<--- sizeof --->|<------------------- 4GB ----------------->|
    1.66 +//
    1.67 +//   | waste | ObjectElements | data array | inaccessible reserved memory |
    1.68 +//                            ^            ^                              ^
    1.69 +//                            |            \                             /
    1.70 +//                      obj->elements       required to be page boundaries
    1.71 +//
    1.72 +static const size_t AsmJSMappedSize = AsmJSPageSize + AsmJSBufferProtectedSize;
    1.73 +#endif // JS_CODEGEN_X64
    1.74 +
    1.75 +#ifdef JS_ION
    1.76 +
    1.77 +// Return whether asm.js optimization is inhibitted by the platform or
    1.78 +// dynamically disabled:
    1.79 +extern bool
    1.80 +IsAsmJSCompilationAvailable(JSContext *cx, unsigned argc, JS::Value *vp);
    1.81 +
    1.82 +#else // JS_ION
    1.83 +
    1.84 +inline bool
    1.85 +IsAsmJSCompilationAvailable(JSContext *cx, unsigned argc, Value *vp)
    1.86 +{
    1.87 +    CallArgs args = CallArgsFromVp(argc, vp);
    1.88 +    args.rval().set(BooleanValue(false));
    1.89 +    return true;
    1.90 +}
    1.91 +
    1.92 +#endif // JS_ION
    1.93 +
    1.94 +// The Asm.js heap length is constrained by the x64 backend heap access scheme
    1.95 +// to be a multiple of the page size which is 4096 bytes, and also constrained
    1.96 +// by the limits of ARM backends 'cmp immediate' instruction which supports a
    1.97 +// complex range for the immediate argument.
    1.98 +//
    1.99 +// ARMv7 mode supports the following immediate constants, and the Thumb T2
   1.100 +// instruction encoding also supports the subset of immediate constants used.
   1.101 +//  abcdefgh 00000000 00000000 00000000
   1.102 +//  00abcdef gh000000 00000000 00000000
   1.103 +//  0000abcd efgh0000 00000000 00000000
   1.104 +//  000000ab cdefgh00 00000000 00000000
   1.105 +//  00000000 abcdefgh 00000000 00000000
   1.106 +//  00000000 00abcdef gh000000 00000000
   1.107 +//  00000000 0000abcd efgh0000 00000000
   1.108 +//  ...
   1.109 +//
   1.110 +// The 4096 page size constraint restricts the length to:
   1.111 +//  xxxxxxxx xxxxxxxx xxxx0000 00000000
   1.112 +//
   1.113 +// Intersecting all the above constraints gives:
   1.114 +//  Heap length 0x40000000 to 0xff000000 quanta 0x01000000
   1.115 +//  Heap length 0x10000000 to 0x3fc00000 quanta 0x00400000
   1.116 +//  Heap length 0x04000000 to 0x0ff00000 quanta 0x00100000
   1.117 +//  Heap length 0x01000000 to 0x03fc0000 quanta 0x00040000
   1.118 +//  Heap length 0x00400000 to 0x00ff0000 quanta 0x00010000
   1.119 +//  Heap length 0x00100000 to 0x003fc000 quanta 0x00004000
   1.120 +//  Heap length 0x00001000 to 0x000ff000 quanta 0x00001000
   1.121 +//
   1.122 +inline uint32_t
   1.123 +RoundUpToNextValidAsmJSHeapLength(uint32_t length)
   1.124 +{
   1.125 +    if (length < 0x00001000u) // Minimum length is the pages size of 4096.
   1.126 +        return 0x1000u;
   1.127 +    if (length < 0x00100000u) // < 1M quanta 4K
   1.128 +        return (length + 0x00000fff) & ~0x00000fff;
   1.129 +    if (length < 0x00400000u) // < 4M quanta 16K
   1.130 +        return (length + 0x00003fff) & ~0x00003fff;
   1.131 +    if (length < 0x01000000u) // < 16M quanta 64K
   1.132 +        return (length + 0x0000ffff) & ~0x0000ffff;
   1.133 +    if (length < 0x04000000u) // < 64M quanta 256K
   1.134 +        return (length + 0x0003ffff) & ~0x0003ffff;
   1.135 +    if (length < 0x10000000u) // < 256M quanta 1M
   1.136 +        return (length + 0x000fffff) & ~0x000fffff;
   1.137 +    if (length < 0x40000000u) // < 1024M quanta 4M
   1.138 +        return (length + 0x003fffff) & ~0x003fffff;
   1.139 +    // < 4096M quanta 16M.  Note zero is returned if over 0xff000000 but such
   1.140 +    // lengths are not currently valid.
   1.141 +    JS_ASSERT(length <= 0xff000000);
   1.142 +    return (length + 0x00ffffff) & ~0x00ffffff;
   1.143 +}
   1.144 +
   1.145 +inline bool
   1.146 +IsValidAsmJSHeapLength(uint32_t length)
   1.147 +{
   1.148 +    if (length <  AsmJSAllocationGranularity)
   1.149 +        return false;
   1.150 +    if (length <= 0x00100000u)
   1.151 +        return (length & 0x00000fff) == 0;
   1.152 +    if (length <= 0x00400000u)
   1.153 +        return (length & 0x00003fff) == 0;
   1.154 +    if (length <= 0x01000000u)
   1.155 +        return (length & 0x0000ffff) == 0;
   1.156 +    if (length <= 0x04000000u)
   1.157 +        return (length & 0x0003ffff) == 0;
   1.158 +    if (length <= 0x10000000u)
   1.159 +        return (length & 0x000fffff) == 0;
   1.160 +    if (length <= 0x40000000u)
   1.161 +        return (length & 0x003fffff) == 0;
   1.162 +    if (length <= 0xff000000u)
   1.163 +        return (length & 0x00ffffff) == 0;
   1.164 +    return false;
   1.165 +}
   1.166 +
   1.167 +} // namespace js
   1.168 +
   1.169 +#endif // jit_AsmJS_h

mercurial