js/src/jit/AsmJS.h

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     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/. */
     7 #ifndef jit_AsmJS_h
     8 #define jit_AsmJS_h
    10 #include <stddef.h>
    12 #include "js/TypeDecls.h"
    13 #include "vm/ObjectImpl.h"
    15 namespace js {
    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 }
    25 typedef frontend::Parser<frontend::FullParseHandler> AsmJSParser;
    26 typedef frontend::ParseContext<frontend::FullParseHandler> AsmJSParseContext;
    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);
    37 // The assumed page size; dynamically checked in CompileAsmJS.
    38 const size_t AsmJSPageSize = 4096;
    40 // The asm.js spec requires that the ArrayBuffer's byteLength be a multiple of 4096.
    41 static const size_t AsmJSAllocationGranularity = 4096;
    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;
    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
    72 #ifdef JS_ION
    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);
    79 #else // JS_ION
    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 }
    89 #endif // JS_ION
    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 }
   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 }
   164 } // namespace js
   166 #endif // jit_AsmJS_h

mercurial