Sat, 03 Jan 2015 20:18:00 +0100
Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.
michael@0 | 1 | /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ |
michael@0 | 2 | // Copyright 2012 the V8 project authors. All rights reserved. |
michael@0 | 3 | // Redistribution and use in source and binary forms, with or without |
michael@0 | 4 | // modification, are permitted provided that the following conditions are |
michael@0 | 5 | // met: |
michael@0 | 6 | // |
michael@0 | 7 | // * Redistributions of source code must retain the above copyright |
michael@0 | 8 | // notice, this list of conditions and the following disclaimer. |
michael@0 | 9 | // * Redistributions in binary form must reproduce the above |
michael@0 | 10 | // copyright notice, this list of conditions and the following |
michael@0 | 11 | // disclaimer in the documentation and/or other materials provided |
michael@0 | 12 | // with the distribution. |
michael@0 | 13 | // * Neither the name of Google Inc. nor the names of its |
michael@0 | 14 | // contributors may be used to endorse or promote products derived |
michael@0 | 15 | // from this software without specific prior written permission. |
michael@0 | 16 | // |
michael@0 | 17 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
michael@0 | 18 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
michael@0 | 19 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
michael@0 | 20 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
michael@0 | 21 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
michael@0 | 22 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
michael@0 | 23 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
michael@0 | 24 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
michael@0 | 25 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
michael@0 | 26 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
michael@0 | 27 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
michael@0 | 28 | |
michael@0 | 29 | #ifndef jit_arm_Simulator_arm_h |
michael@0 | 30 | #define jit_arm_Simulator_arm_h |
michael@0 | 31 | |
michael@0 | 32 | #ifdef JS_ARM_SIMULATOR |
michael@0 | 33 | |
michael@0 | 34 | #include "jit/arm/Architecture-arm.h" |
michael@0 | 35 | #include "jit/IonTypes.h" |
michael@0 | 36 | |
michael@0 | 37 | namespace js { |
michael@0 | 38 | namespace jit { |
michael@0 | 39 | |
michael@0 | 40 | class SimulatorRuntime; |
michael@0 | 41 | SimulatorRuntime *CreateSimulatorRuntime(); |
michael@0 | 42 | void DestroySimulatorRuntime(SimulatorRuntime *srt); |
michael@0 | 43 | |
michael@0 | 44 | // VFP rounding modes. See ARM DDI 0406B Page A2-29. |
michael@0 | 45 | enum VFPRoundingMode { |
michael@0 | 46 | SimRN = 0 << 22, // Round to Nearest. |
michael@0 | 47 | SimRP = 1 << 22, // Round towards Plus Infinity. |
michael@0 | 48 | SimRM = 2 << 22, // Round towards Minus Infinity. |
michael@0 | 49 | SimRZ = 3 << 22, // Round towards zero. |
michael@0 | 50 | |
michael@0 | 51 | // Aliases. |
michael@0 | 52 | kRoundToNearest = SimRN, |
michael@0 | 53 | kRoundToPlusInf = SimRP, |
michael@0 | 54 | kRoundToMinusInf = SimRM, |
michael@0 | 55 | kRoundToZero = SimRZ |
michael@0 | 56 | }; |
michael@0 | 57 | |
michael@0 | 58 | const uint32_t kVFPRoundingModeMask = 3 << 22; |
michael@0 | 59 | |
michael@0 | 60 | typedef int32_t Instr; |
michael@0 | 61 | class SimInstruction; |
michael@0 | 62 | |
michael@0 | 63 | class Simulator |
michael@0 | 64 | { |
michael@0 | 65 | friend class Redirection; |
michael@0 | 66 | |
michael@0 | 67 | public: |
michael@0 | 68 | friend class ArmDebugger; |
michael@0 | 69 | enum Register { |
michael@0 | 70 | no_reg = -1, |
michael@0 | 71 | r0 = 0, r1, r2, r3, r4, r5, r6, r7, |
michael@0 | 72 | r8, r9, r10, r11, r12, r13, r14, r15, |
michael@0 | 73 | num_registers, |
michael@0 | 74 | sp = 13, |
michael@0 | 75 | lr = 14, |
michael@0 | 76 | pc = 15, |
michael@0 | 77 | s0 = 0, s1, s2, s3, s4, s5, s6, s7, |
michael@0 | 78 | s8, s9, s10, s11, s12, s13, s14, s15, |
michael@0 | 79 | s16, s17, s18, s19, s20, s21, s22, s23, |
michael@0 | 80 | s24, s25, s26, s27, s28, s29, s30, s31, |
michael@0 | 81 | num_s_registers = 32, |
michael@0 | 82 | d0 = 0, d1, d2, d3, d4, d5, d6, d7, |
michael@0 | 83 | d8, d9, d10, d11, d12, d13, d14, d15, |
michael@0 | 84 | d16, d17, d18, d19, d20, d21, d22, d23, |
michael@0 | 85 | d24, d25, d26, d27, d28, d29, d30, d31, |
michael@0 | 86 | num_d_registers = 32, |
michael@0 | 87 | q0 = 0, q1, q2, q3, q4, q5, q6, q7, |
michael@0 | 88 | q8, q9, q10, q11, q12, q13, q14, q15, |
michael@0 | 89 | num_q_registers = 16 |
michael@0 | 90 | }; |
michael@0 | 91 | |
michael@0 | 92 | explicit Simulator(SimulatorRuntime *srt); |
michael@0 | 93 | ~Simulator(); |
michael@0 | 94 | |
michael@0 | 95 | // The currently executing Simulator instance. Potentially there can be one |
michael@0 | 96 | // for each native thread. |
michael@0 | 97 | static Simulator *Current(); |
michael@0 | 98 | |
michael@0 | 99 | static inline uintptr_t StackLimit() { |
michael@0 | 100 | return Simulator::Current()->stackLimit(); |
michael@0 | 101 | } |
michael@0 | 102 | |
michael@0 | 103 | // Accessors for register state. Reading the pc value adheres to the ARM |
michael@0 | 104 | // architecture specification and is off by a 8 from the currently executing |
michael@0 | 105 | // instruction. |
michael@0 | 106 | void set_register(int reg, int32_t value); |
michael@0 | 107 | int32_t get_register(int reg) const; |
michael@0 | 108 | double get_double_from_register_pair(int reg); |
michael@0 | 109 | void set_register_pair_from_double(int reg, double* value); |
michael@0 | 110 | void set_dw_register(int dreg, const int* dbl); |
michael@0 | 111 | |
michael@0 | 112 | // Support for VFP. |
michael@0 | 113 | void get_d_register(int dreg, uint64_t* value); |
michael@0 | 114 | void set_d_register(int dreg, const uint64_t* value); |
michael@0 | 115 | void get_d_register(int dreg, uint32_t* value); |
michael@0 | 116 | void set_d_register(int dreg, const uint32_t* value); |
michael@0 | 117 | void get_q_register(int qreg, uint64_t* value); |
michael@0 | 118 | void set_q_register(int qreg, const uint64_t* value); |
michael@0 | 119 | void get_q_register(int qreg, uint32_t* value); |
michael@0 | 120 | void set_q_register(int qreg, const uint32_t* value); |
michael@0 | 121 | void set_s_register(int reg, unsigned int value); |
michael@0 | 122 | unsigned int get_s_register(int reg) const; |
michael@0 | 123 | |
michael@0 | 124 | void set_d_register_from_double(int dreg, const double& dbl) { |
michael@0 | 125 | setVFPRegister<double, 2>(dreg, dbl); |
michael@0 | 126 | } |
michael@0 | 127 | double get_double_from_d_register(int dreg) { |
michael@0 | 128 | return getFromVFPRegister<double, 2>(dreg); |
michael@0 | 129 | } |
michael@0 | 130 | void set_s_register_from_float(int sreg, const float flt) { |
michael@0 | 131 | setVFPRegister<float, 1>(sreg, flt); |
michael@0 | 132 | } |
michael@0 | 133 | float get_float_from_s_register(int sreg) { |
michael@0 | 134 | return getFromVFPRegister<float, 1>(sreg); |
michael@0 | 135 | } |
michael@0 | 136 | void set_s_register_from_sinteger(int sreg, const int sint) { |
michael@0 | 137 | setVFPRegister<int, 1>(sreg, sint); |
michael@0 | 138 | } |
michael@0 | 139 | int get_sinteger_from_s_register(int sreg) { |
michael@0 | 140 | return getFromVFPRegister<int, 1>(sreg); |
michael@0 | 141 | } |
michael@0 | 142 | |
michael@0 | 143 | // Special case of set_register and get_register to access the raw PC value. |
michael@0 | 144 | void set_pc(int32_t value); |
michael@0 | 145 | int32_t get_pc() const; |
michael@0 | 146 | |
michael@0 | 147 | void set_resume_pc(int32_t value) { |
michael@0 | 148 | resume_pc_ = value; |
michael@0 | 149 | } |
michael@0 | 150 | |
michael@0 | 151 | uintptr_t stackLimit() const; |
michael@0 | 152 | bool overRecursed(uintptr_t newsp = 0) const; |
michael@0 | 153 | bool overRecursedWithExtra(uint32_t extra) const; |
michael@0 | 154 | |
michael@0 | 155 | // Executes ARM instructions until the PC reaches end_sim_pc. |
michael@0 | 156 | template<bool EnableStopSimAt> |
michael@0 | 157 | void execute(); |
michael@0 | 158 | |
michael@0 | 159 | // Sets up the simulator state and grabs the result on return. |
michael@0 | 160 | int64_t call(uint8_t* entry, int argument_count, ...); |
michael@0 | 161 | |
michael@0 | 162 | // Debugger input. |
michael@0 | 163 | void setLastDebuggerInput(char *input); |
michael@0 | 164 | char *lastDebuggerInput() { return lastDebuggerInput_; } |
michael@0 | 165 | |
michael@0 | 166 | // Returns true if pc register contains one of the 'special_values' defined |
michael@0 | 167 | // below (bad_lr, end_sim_pc). |
michael@0 | 168 | bool has_bad_pc() const; |
michael@0 | 169 | |
michael@0 | 170 | private: |
michael@0 | 171 | enum special_values { |
michael@0 | 172 | // Known bad pc value to ensure that the simulator does not execute |
michael@0 | 173 | // without being properly setup. |
michael@0 | 174 | bad_lr = -1, |
michael@0 | 175 | // A pc value used to signal the simulator to stop execution. Generally |
michael@0 | 176 | // the lr is set to this value on transition from native C code to |
michael@0 | 177 | // simulated execution, so that the simulator can "return" to the native |
michael@0 | 178 | // C code. |
michael@0 | 179 | end_sim_pc = -2 |
michael@0 | 180 | }; |
michael@0 | 181 | |
michael@0 | 182 | // Checks if the current instruction should be executed based on its |
michael@0 | 183 | // condition bits. |
michael@0 | 184 | inline bool conditionallyExecute(SimInstruction* instr); |
michael@0 | 185 | |
michael@0 | 186 | // Helper functions to set the conditional flags in the architecture state. |
michael@0 | 187 | void setNZFlags(int32_t val); |
michael@0 | 188 | void setCFlag(bool val); |
michael@0 | 189 | void setVFlag(bool val); |
michael@0 | 190 | bool carryFrom(int32_t left, int32_t right, int32_t carry = 0); |
michael@0 | 191 | bool borrowFrom(int32_t left, int32_t right); |
michael@0 | 192 | bool overflowFrom(int32_t alu_out, int32_t left, int32_t right, bool addition); |
michael@0 | 193 | |
michael@0 | 194 | inline int getCarry() { return c_flag_ ? 1 : 0; }; |
michael@0 | 195 | |
michael@0 | 196 | // Support for VFP. |
michael@0 | 197 | void compute_FPSCR_Flags(double val1, double val2); |
michael@0 | 198 | void copy_FPSCR_to_APSR(); |
michael@0 | 199 | inline double canonicalizeNaN(double value); |
michael@0 | 200 | |
michael@0 | 201 | // Helper functions to decode common "addressing" modes |
michael@0 | 202 | int32_t getShiftRm(SimInstruction *instr, bool* carry_out); |
michael@0 | 203 | int32_t getImm(SimInstruction *instr, bool* carry_out); |
michael@0 | 204 | int32_t processPU(SimInstruction *instr, int num_regs, int operand_size, |
michael@0 | 205 | intptr_t *start_address, intptr_t *end_address); |
michael@0 | 206 | void handleRList(SimInstruction *instr, bool load); |
michael@0 | 207 | void handleVList(SimInstruction *inst); |
michael@0 | 208 | void softwareInterrupt(SimInstruction *instr); |
michael@0 | 209 | |
michael@0 | 210 | // Stop helper functions. |
michael@0 | 211 | inline bool isStopInstruction(SimInstruction *instr); |
michael@0 | 212 | inline bool isWatchedStop(uint32_t bkpt_code); |
michael@0 | 213 | inline bool isEnabledStop(uint32_t bkpt_code); |
michael@0 | 214 | inline void enableStop(uint32_t bkpt_code); |
michael@0 | 215 | inline void disableStop(uint32_t bkpt_code); |
michael@0 | 216 | inline void increaseStopCounter(uint32_t bkpt_code); |
michael@0 | 217 | void printStopInfo(uint32_t code); |
michael@0 | 218 | |
michael@0 | 219 | // Read and write memory. |
michael@0 | 220 | inline uint8_t readBU(int32_t addr); |
michael@0 | 221 | inline int8_t readB(int32_t addr); |
michael@0 | 222 | inline void writeB(int32_t addr, uint8_t value); |
michael@0 | 223 | inline void writeB(int32_t addr, int8_t value); |
michael@0 | 224 | |
michael@0 | 225 | inline uint16_t readHU(int32_t addr, SimInstruction *instr); |
michael@0 | 226 | inline int16_t readH(int32_t addr, SimInstruction *instr); |
michael@0 | 227 | // Note: Overloaded on the sign of the value. |
michael@0 | 228 | inline void writeH(int32_t addr, uint16_t value, SimInstruction *instr); |
michael@0 | 229 | inline void writeH(int32_t addr, int16_t value, SimInstruction *instr); |
michael@0 | 230 | |
michael@0 | 231 | inline int readW(int32_t addr, SimInstruction *instr); |
michael@0 | 232 | inline void writeW(int32_t addr, int value, SimInstruction *instr); |
michael@0 | 233 | |
michael@0 | 234 | int32_t *readDW(int32_t addr); |
michael@0 | 235 | void writeDW(int32_t addr, int32_t value1, int32_t value2); |
michael@0 | 236 | |
michael@0 | 237 | // Executing is handled based on the instruction type. |
michael@0 | 238 | // Both type 0 and type 1 rolled into one. |
michael@0 | 239 | void decodeType01(SimInstruction *instr); |
michael@0 | 240 | void decodeType2(SimInstruction *instr); |
michael@0 | 241 | void decodeType3(SimInstruction *instr); |
michael@0 | 242 | void decodeType4(SimInstruction *instr); |
michael@0 | 243 | void decodeType5(SimInstruction *instr); |
michael@0 | 244 | void decodeType6(SimInstruction *instr); |
michael@0 | 245 | void decodeType7(SimInstruction *instr); |
michael@0 | 246 | |
michael@0 | 247 | // Support for VFP. |
michael@0 | 248 | void decodeTypeVFP(SimInstruction *instr); |
michael@0 | 249 | void decodeType6CoprocessorIns(SimInstruction *instr); |
michael@0 | 250 | void decodeSpecialCondition(SimInstruction *instr); |
michael@0 | 251 | |
michael@0 | 252 | void decodeVMOVBetweenCoreAndSinglePrecisionRegisters(SimInstruction *instr); |
michael@0 | 253 | void decodeVCMP(SimInstruction *instr); |
michael@0 | 254 | void decodeVCVTBetweenDoubleAndSingle(SimInstruction *instr); |
michael@0 | 255 | void decodeVCVTBetweenFloatingPointAndInteger(SimInstruction *instr); |
michael@0 | 256 | void decodeVCVTBetweenFloatingPointAndIntegerFrac(SimInstruction *instr); |
michael@0 | 257 | |
michael@0 | 258 | // Executes one instruction. |
michael@0 | 259 | void instructionDecode(SimInstruction *instr); |
michael@0 | 260 | |
michael@0 | 261 | public: |
michael@0 | 262 | static bool ICacheCheckingEnabled; |
michael@0 | 263 | static void FlushICache(void *start, size_t size); |
michael@0 | 264 | |
michael@0 | 265 | static int64_t StopSimAt; |
michael@0 | 266 | |
michael@0 | 267 | // Runtime call support. |
michael@0 | 268 | static void *RedirectNativeFunction(void *nativeFunction, ABIFunctionType type); |
michael@0 | 269 | |
michael@0 | 270 | private: |
michael@0 | 271 | // Handle arguments and return value for runtime FP functions. |
michael@0 | 272 | void getFpArgs(double *x, double *y, int32_t *z); |
michael@0 | 273 | void setCallResultDouble(double result); |
michael@0 | 274 | void setCallResultFloat(float result); |
michael@0 | 275 | void setCallResult(int64_t res); |
michael@0 | 276 | void scratchVolatileRegisters(bool scratchFloat = true); |
michael@0 | 277 | |
michael@0 | 278 | template<class ReturnType, int register_size> |
michael@0 | 279 | ReturnType getFromVFPRegister(int reg_index); |
michael@0 | 280 | |
michael@0 | 281 | template<class InputType, int register_size> |
michael@0 | 282 | void setVFPRegister(int reg_index, const InputType& value); |
michael@0 | 283 | |
michael@0 | 284 | void callInternal(uint8_t* entry); |
michael@0 | 285 | |
michael@0 | 286 | // Architecture state. |
michael@0 | 287 | // Saturating instructions require a Q flag to indicate saturation. |
michael@0 | 288 | // There is currently no way to read the CPSR directly, and thus read the Q |
michael@0 | 289 | // flag, so this is left unimplemented. |
michael@0 | 290 | int32_t registers_[16]; |
michael@0 | 291 | bool n_flag_; |
michael@0 | 292 | bool z_flag_; |
michael@0 | 293 | bool c_flag_; |
michael@0 | 294 | bool v_flag_; |
michael@0 | 295 | |
michael@0 | 296 | // VFP architecture state. |
michael@0 | 297 | uint32_t vfp_registers_[num_d_registers * 2]; |
michael@0 | 298 | bool n_flag_FPSCR_; |
michael@0 | 299 | bool z_flag_FPSCR_; |
michael@0 | 300 | bool c_flag_FPSCR_; |
michael@0 | 301 | bool v_flag_FPSCR_; |
michael@0 | 302 | |
michael@0 | 303 | // VFP rounding mode. See ARM DDI 0406B Page A2-29. |
michael@0 | 304 | VFPRoundingMode FPSCR_rounding_mode_; |
michael@0 | 305 | bool FPSCR_default_NaN_mode_; |
michael@0 | 306 | |
michael@0 | 307 | // VFP FP exception flags architecture state. |
michael@0 | 308 | bool inv_op_vfp_flag_; |
michael@0 | 309 | bool div_zero_vfp_flag_; |
michael@0 | 310 | bool overflow_vfp_flag_; |
michael@0 | 311 | bool underflow_vfp_flag_; |
michael@0 | 312 | bool inexact_vfp_flag_; |
michael@0 | 313 | |
michael@0 | 314 | // Simulator support. |
michael@0 | 315 | char *stack_; |
michael@0 | 316 | bool pc_modified_; |
michael@0 | 317 | int64_t icount_; |
michael@0 | 318 | |
michael@0 | 319 | int32_t resume_pc_; |
michael@0 | 320 | |
michael@0 | 321 | // Debugger input. |
michael@0 | 322 | char *lastDebuggerInput_; |
michael@0 | 323 | |
michael@0 | 324 | // Registered breakpoints. |
michael@0 | 325 | SimInstruction *break_pc_; |
michael@0 | 326 | Instr break_instr_; |
michael@0 | 327 | |
michael@0 | 328 | SimulatorRuntime *srt_; |
michael@0 | 329 | |
michael@0 | 330 | // A stop is watched if its code is less than kNumOfWatchedStops. |
michael@0 | 331 | // Only watched stops support enabling/disabling and the counter feature. |
michael@0 | 332 | static const uint32_t kNumOfWatchedStops = 256; |
michael@0 | 333 | |
michael@0 | 334 | // Breakpoint is disabled if bit 31 is set. |
michael@0 | 335 | static const uint32_t kStopDisabledBit = 1 << 31; |
michael@0 | 336 | |
michael@0 | 337 | // A stop is enabled, meaning the simulator will stop when meeting the |
michael@0 | 338 | // instruction, if bit 31 of watched_stops_[code].count is unset. |
michael@0 | 339 | // The value watched_stops_[code].count & ~(1 << 31) indicates how many times |
michael@0 | 340 | // the breakpoint was hit or gone through. |
michael@0 | 341 | struct StopCountAndDesc { |
michael@0 | 342 | uint32_t count; |
michael@0 | 343 | char *desc; |
michael@0 | 344 | }; |
michael@0 | 345 | StopCountAndDesc watched_stops_[kNumOfWatchedStops]; |
michael@0 | 346 | |
michael@0 | 347 | public: |
michael@0 | 348 | int64_t icount() { |
michael@0 | 349 | return icount_; |
michael@0 | 350 | } |
michael@0 | 351 | |
michael@0 | 352 | }; |
michael@0 | 353 | |
michael@0 | 354 | #define JS_CHECK_SIMULATOR_RECURSION_WITH_EXTRA(cx, extra, onerror) \ |
michael@0 | 355 | JS_BEGIN_MACRO \ |
michael@0 | 356 | if (cx->mainThread().simulator()->overRecursedWithExtra(extra)) { \ |
michael@0 | 357 | js_ReportOverRecursed(cx); \ |
michael@0 | 358 | onerror; \ |
michael@0 | 359 | } \ |
michael@0 | 360 | JS_END_MACRO |
michael@0 | 361 | |
michael@0 | 362 | } // namespace jit |
michael@0 | 363 | } // namespace js |
michael@0 | 364 | |
michael@0 | 365 | #endif /* JS_ARM_SIMULATOR */ |
michael@0 | 366 | |
michael@0 | 367 | #endif /* jit_arm_Simulator_arm_h */ |