1/* 2 * Copyright (C) 2008, 2009, 2013 Apple Inc. All rights reserved. 3 * Copyright (C) 2008 Cameron Zwarich <cwzwarich@uwaterloo.ca> 4 * Copyright (C) Research In Motion Limited 2010, 2011. All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of 16 * its contributors may be used to endorse or promote products derived 17 * from this software without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY 20 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 21 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 22 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY 23 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 24 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 25 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 26 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 28 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 */ 30 31#include "config.h" 32 33#if ENABLE(JIT) 34#include "JITStubs.h" 35 36#include "CommonSlowPaths.h" 37#include "Arguments.h" 38#include "ArrayConstructor.h" 39#include "CallFrame.h" 40#include "CodeBlock.h" 41#include "CodeProfiling.h" 42#include "DFGOSREntry.h" 43#include "Debugger.h" 44#include "ExceptionHelpers.h" 45#include "GetterSetter.h" 46#include "Heap.h" 47#include <wtf/InlineASM.h> 48#include "JIT.h" 49#include "JITExceptions.h" 50#include "JSActivation.h" 51#include "JSArray.h" 52#include "JSFunction.h" 53#include "JSGlobalObjectFunctions.h" 54#include "JSNameScope.h" 55#include "JSNotAnObject.h" 56#include "JSPropertyNameIterator.h" 57#include "JSString.h" 58#include "JSWithScope.h" 59#include "LegacyProfiler.h" 60#include "NameInstance.h" 61#include "ObjectConstructor.h" 62#include "ObjectPrototype.h" 63#include "Operations.h" 64#include "Parser.h" 65#include "RegExpObject.h" 66#include "RegExpPrototype.h" 67#include "Register.h" 68#include "RepatchBuffer.h" 69#include "SamplingTool.h" 70#include "Strong.h" 71#include "StructureRareDataInlines.h" 72#include <wtf/StdLibExtras.h> 73#include <stdarg.h> 74#include <stdio.h> 75 76using namespace std; 77 78namespace JSC { 79 80#if USE(JSVALUE32_64) 81 82#if COMPILER(GCC) && CPU(X86) 83 84// These ASSERTs remind you that, if you change the layout of JITStackFrame, you 85// need to change the assembly trampolines below to match. 86COMPILE_ASSERT(offsetof(struct JITStackFrame, code) % 16 == 0x0, JITStackFrame_maintains_16byte_stack_alignment); 87COMPILE_ASSERT(offsetof(struct JITStackFrame, savedEBX) == 0x3c, JITStackFrame_stub_argument_space_matches_ctiTrampoline); 88COMPILE_ASSERT(offsetof(struct JITStackFrame, callFrame) == 0x58, JITStackFrame_callFrame_offset_matches_ctiTrampoline); 89COMPILE_ASSERT(offsetof(struct JITStackFrame, code) == 0x50, JITStackFrame_code_offset_matches_ctiTrampoline); 90 91asm ( 92".text\n" 93".globl " SYMBOL_STRING(ctiTrampoline) "\n" 94HIDE_SYMBOL(ctiTrampoline) "\n" 95SYMBOL_STRING(ctiTrampoline) ":" "\n" 96 "pushl %ebp" "\n" 97 "movl %esp, %ebp" "\n" 98 "pushl %esi" "\n" 99 "pushl %edi" "\n" 100 "pushl %ebx" "\n" 101 "subl $0x3c, %esp" "\n" 102 "movw $0x02FF, %bx" "\n" 103 "movw %bx, 0(%esp)" "\n" 104 "fldcw 0(%esp)" "\n" 105 "movl 0x58(%esp), %edi" "\n" 106 "call *0x50(%esp)" "\n" 107 "addl $0x3c, %esp" "\n" 108 "popl %ebx" "\n" 109 "popl %edi" "\n" 110 "popl %esi" "\n" 111 "popl %ebp" "\n" 112 "ffree %st(1)" "\n" 113 "ret" "\n" 114".globl " SYMBOL_STRING(ctiTrampolineEnd) "\n" 115HIDE_SYMBOL(ctiTrampolineEnd) "\n" 116SYMBOL_STRING(ctiTrampolineEnd) ":" "\n" 117); 118 119asm ( 120".globl " SYMBOL_STRING(ctiVMThrowTrampoline) "\n" 121HIDE_SYMBOL(ctiVMThrowTrampoline) "\n" 122SYMBOL_STRING(ctiVMThrowTrampoline) ":" "\n" 123 "movl %esp, %ecx" "\n" 124 "call " LOCAL_REFERENCE(cti_vm_throw) "\n" 125 "int3" "\n" 126); 127 128asm ( 129".globl " SYMBOL_STRING(ctiOpThrowNotCaught) "\n" 130HIDE_SYMBOL(ctiOpThrowNotCaught) "\n" 131SYMBOL_STRING(ctiOpThrowNotCaught) ":" "\n" 132 "addl $0x3c, %esp" "\n" 133 "popl %ebx" "\n" 134 "popl %edi" "\n" 135 "popl %esi" "\n" 136 "popl %ebp" "\n" 137 "ret" "\n" 138); 139 140#elif COMPILER(GCC) && CPU(X86_64) 141 142// These ASSERTs remind you that, if you change the layout of JITStackFrame, you 143// need to change the assembly trampolines below to match. 144COMPILE_ASSERT(offsetof(struct JITStackFrame, code) % 32 == 0x0, JITStackFrame_maintains_32byte_stack_alignment); 145COMPILE_ASSERT(offsetof(struct JITStackFrame, savedRBX) == 0x48, JITStackFrame_stub_argument_space_matches_ctiTrampoline); 146COMPILE_ASSERT(offsetof(struct JITStackFrame, callFrame) == 0x90, JITStackFrame_callFrame_offset_matches_ctiTrampoline); 147COMPILE_ASSERT(offsetof(struct JITStackFrame, code) == 0x80, JITStackFrame_code_offset_matches_ctiTrampoline); 148 149asm ( 150".globl " SYMBOL_STRING(ctiTrampoline) "\n" 151HIDE_SYMBOL(ctiTrampoline) "\n" 152SYMBOL_STRING(ctiTrampoline) ":" "\n" 153 "pushq %rbp" "\n" 154 "movq %rsp, %rbp" "\n" 155 "pushq %r12" "\n" 156 "pushq %r13" "\n" 157 "pushq %r14" "\n" 158 "pushq %r15" "\n" 159 "pushq %rbx" "\n" 160 "subq $0x48, %rsp" "\n" 161 "movq $512, %r12" "\n" 162 "movq $0xFFFF000000000000, %r14" "\n" 163 "movq $0xFFFF000000000002, %r15" "\n" 164 "movq 0x90(%rsp), %r13" "\n" 165 "call *0x80(%rsp)" "\n" 166 "addq $0x48, %rsp" "\n" 167 "popq %rbx" "\n" 168 "popq %r15" "\n" 169 "popq %r14" "\n" 170 "popq %r13" "\n" 171 "popq %r12" "\n" 172 "popq %rbp" "\n" 173 "ret" "\n" 174".globl " SYMBOL_STRING(ctiTrampolineEnd) "\n" 175HIDE_SYMBOL(ctiTrampolineEnd) "\n" 176SYMBOL_STRING(ctiTrampolineEnd) ":" "\n" 177); 178 179asm ( 180".globl " SYMBOL_STRING(ctiVMThrowTrampoline) "\n" 181HIDE_SYMBOL(ctiVMThrowTrampoline) "\n" 182SYMBOL_STRING(ctiVMThrowTrampoline) ":" "\n" 183 "movq %rsp, %rdi" "\n" 184 "call " LOCAL_REFERENCE(cti_vm_throw) "\n" 185 "int3" "\n" 186); 187 188asm ( 189".globl " SYMBOL_STRING(ctiOpThrowNotCaught) "\n" 190HIDE_SYMBOL(ctiOpThrowNotCaught) "\n" 191SYMBOL_STRING(ctiOpThrowNotCaught) ":" "\n" 192 "addq $0x48, %rsp" "\n" 193 "popq %rbx" "\n" 194 "popq %r15" "\n" 195 "popq %r14" "\n" 196 "popq %r13" "\n" 197 "popq %r12" "\n" 198 "popq %rbp" "\n" 199 "ret" "\n" 200); 201 202#elif (COMPILER(GCC) || COMPILER(RVCT)) && CPU(ARM_THUMB2) 203 204#define THUNK_RETURN_ADDRESS_OFFSET 0x38 205#define PRESERVED_RETURN_ADDRESS_OFFSET 0x3C 206#define PRESERVED_R4_OFFSET 0x40 207#define PRESERVED_R5_OFFSET 0x44 208#define PRESERVED_R6_OFFSET 0x48 209#define PRESERVED_R7_OFFSET 0x4C 210#define PRESERVED_R8_OFFSET 0x50 211#define PRESERVED_R9_OFFSET 0x54 212#define PRESERVED_R10_OFFSET 0x58 213#define PRESERVED_R11_OFFSET 0x5C 214#define REGISTER_FILE_OFFSET 0x60 215#define FIRST_STACK_ARGUMENT 0x68 216 217#elif (COMPILER(GCC) || COMPILER(MSVC) || COMPILER(RVCT)) && CPU(ARM_TRADITIONAL) 218 219// Also update the MSVC section (defined at DEFINE_STUB_FUNCTION) 220// when changing one of the following values. 221#define THUNK_RETURN_ADDRESS_OFFSET 64 222#define PRESERVEDR4_OFFSET 68 223 224#elif COMPILER(MSVC) && CPU(X86) 225 226// These ASSERTs remind you that, if you change the layout of JITStackFrame, you 227// need to change the assembly trampolines below to match. 228COMPILE_ASSERT(offsetof(struct JITStackFrame, code) % 16 == 0x0, JITStackFrame_maintains_16byte_stack_alignment); 229COMPILE_ASSERT(offsetof(struct JITStackFrame, savedEBX) == 0x3c, JITStackFrame_stub_argument_space_matches_ctiTrampoline); 230COMPILE_ASSERT(offsetof(struct JITStackFrame, callFrame) == 0x58, JITStackFrame_callFrame_offset_matches_ctiTrampoline); 231COMPILE_ASSERT(offsetof(struct JITStackFrame, code) == 0x50, JITStackFrame_code_offset_matches_ctiTrampoline); 232 233extern "C" { 234 235 __declspec(naked) EncodedJSValue ctiTrampoline(void* code, JSStack*, CallFrame*, void* /*unused1*/, void* /*unused2*/, VM*) 236 { 237 __asm { 238 push ebp; 239 mov ebp, esp; 240 push esi; 241 push edi; 242 push ebx; 243 sub esp, 0x3c; 244 mov ecx, esp; 245 mov edi, [esp + 0x58]; 246 call [esp + 0x50]; 247 add esp, 0x3c; 248 pop ebx; 249 pop edi; 250 pop esi; 251 pop ebp; 252 ret; 253 } 254 } 255 256 __declspec(naked) void ctiVMThrowTrampoline() 257 { 258 __asm { 259 mov ecx, esp; 260 call cti_vm_throw; 261 add esp, 0x3c; 262 pop ebx; 263 pop edi; 264 pop esi; 265 pop ebp; 266 ret; 267 } 268 } 269 270 __declspec(naked) void ctiOpThrowNotCaught() 271 { 272 __asm { 273 add esp, 0x3c; 274 pop ebx; 275 pop edi; 276 pop esi; 277 pop ebp; 278 ret; 279 } 280 } 281} 282 283#elif CPU(MIPS) 284 285#define PRESERVED_GP_OFFSET 60 286#define PRESERVED_S0_OFFSET 64 287#define PRESERVED_S1_OFFSET 68 288#define PRESERVED_S2_OFFSET 72 289#define PRESERVED_S3_OFFSET 76 290#define PRESERVED_S4_OFFSET 80 291#define PRESERVED_RETURN_ADDRESS_OFFSET 84 292#define THUNK_RETURN_ADDRESS_OFFSET 88 293#define REGISTER_FILE_OFFSET 92 294#define GLOBAL_DATA_OFFSET 108 295#define STACK_LENGTH 112 296#elif CPU(SH4) 297#define SYMBOL_STRING(name) #name 298/* code (r4), JSStack* (r5), CallFrame* (r6), void* unused1 (r7), void* unused2(sp), VM (sp)*/ 299 300asm volatile ( 301".text\n" 302".globl " SYMBOL_STRING(ctiTrampoline) "\n" 303HIDE_SYMBOL(ctiTrampoline) "\n" 304SYMBOL_STRING(ctiTrampoline) ":" "\n" 305 "mov.l r7, @-r15" "\n" 306 "mov.l r6, @-r15" "\n" 307 "mov.l r5, @-r15" "\n" 308 "mov.l r14, @-r15" "\n" 309 "sts.l pr, @-r15" "\n" 310 "mov.l r13, @-r15" "\n" 311 "mov.l r11, @-r15" "\n" 312 "mov.l r10, @-r15" "\n" 313 "add #-60, r15" "\n" 314 "mov r6, r14" "\n" 315 "jsr @r4" "\n" 316 "nop" "\n" 317 "add #60, r15" "\n" 318 "mov.l @r15+,r10" "\n" 319 "mov.l @r15+,r11" "\n" 320 "mov.l @r15+,r13" "\n" 321 "lds.l @r15+,pr" "\n" 322 "mov.l @r15+,r14" "\n" 323 "add #12, r15" "\n" 324 "rts" "\n" 325 "nop" "\n" 326".globl " SYMBOL_STRING(ctiTrampolineEnd) "\n" 327HIDE_SYMBOL(ctiTrampolineEnd) "\n" 328SYMBOL_STRING(ctiTrampolineEnd) ":" "\n" 329); 330 331asm volatile ( 332".globl " SYMBOL_STRING(ctiVMThrowTrampoline) "\n" 333HIDE_SYMBOL(ctiVMThrowTrampoline) "\n" 334SYMBOL_STRING(ctiVMThrowTrampoline) ":" "\n" 335 "mov.l .L2"SYMBOL_STRING(cti_vm_throw)",r0" "\n" 336 "mov r15, r4" "\n" 337 "mov.l @(r0,r12),r11" "\n" 338 "jsr @r11" "\n" 339 "nop" "\n" 340 "add #60, r15" "\n" 341 "mov.l @r15+,r10" "\n" 342 "mov.l @r15+,r11" "\n" 343 "mov.l @r15+,r13" "\n" 344 "lds.l @r15+,pr" "\n" 345 "mov.l @r15+,r14" "\n" 346 "add #12, r15" "\n" 347 "rts" "\n" 348 "nop" "\n" 349 ".align 2" "\n" 350 ".L2"SYMBOL_STRING(cti_vm_throw)":.long " SYMBOL_STRING(cti_vm_throw)"@GOT \n" 351); 352 353asm volatile ( 354".globl " SYMBOL_STRING(ctiOpThrowNotCaught) "\n" 355HIDE_SYMBOL(ctiOpThrowNotCaught) "\n" 356SYMBOL_STRING(ctiOpThrowNotCaught) ":" "\n" 357 "add #60, r15" "\n" 358 "mov.l @r15+,r10" "\n" 359 "mov.l @r15+,r11" "\n" 360 "mov.l @r15+,r13" "\n" 361 "lds.l @r15+,pr" "\n" 362 "mov.l @r15+,r14" "\n" 363 "add #12, r15" "\n" 364 "rts" "\n" 365 "nop" "\n" 366); 367#else 368 #error "JIT not supported on this platform." 369#endif 370 371#else // USE(JSVALUE32_64) 372 373#if COMPILER(GCC) && CPU(X86_64) && !OS(WINDOWS) 374 375// These ASSERTs remind you that, if you change the layout of JITStackFrame, you 376// need to change the assembly trampolines below to match. 377COMPILE_ASSERT(offsetof(struct JITStackFrame, callFrame) == 0x58, JITStackFrame_callFrame_offset_matches_ctiTrampoline); 378COMPILE_ASSERT(offsetof(struct JITStackFrame, code) == 0x48, JITStackFrame_code_offset_matches_ctiTrampoline); 379COMPILE_ASSERT(offsetof(struct JITStackFrame, savedRBX) == 0x78, JITStackFrame_stub_argument_space_matches_ctiTrampoline); 380 381asm ( 382".text\n" 383".globl " SYMBOL_STRING(ctiTrampoline) "\n" 384HIDE_SYMBOL(ctiTrampoline) "\n" 385SYMBOL_STRING(ctiTrampoline) ":" "\n" 386 "pushq %rbp" "\n" 387 "movq %rsp, %rbp" "\n" 388 "pushq %r12" "\n" 389 "pushq %r13" "\n" 390 "pushq %r14" "\n" 391 "pushq %r15" "\n" 392 "pushq %rbx" "\n" 393 // Form the JIT stubs area 394 "pushq %r9" "\n" 395 "pushq %r8" "\n" 396 "pushq %rcx" "\n" 397 "pushq %rdx" "\n" 398 "pushq %rsi" "\n" 399 "pushq %rdi" "\n" 400 "subq $0x48, %rsp" "\n" 401 "movq $512, %r12" "\n" 402 "movq $0xFFFF000000000000, %r14" "\n" 403 "movq $0xFFFF000000000002, %r15" "\n" 404 "movq %rdx, %r13" "\n" 405 "call *%rdi" "\n" 406 "addq $0x78, %rsp" "\n" 407 "popq %rbx" "\n" 408 "popq %r15" "\n" 409 "popq %r14" "\n" 410 "popq %r13" "\n" 411 "popq %r12" "\n" 412 "popq %rbp" "\n" 413 "ret" "\n" 414".globl " SYMBOL_STRING(ctiTrampolineEnd) "\n" 415HIDE_SYMBOL(ctiTrampolineEnd) "\n" 416SYMBOL_STRING(ctiTrampolineEnd) ":" "\n" 417); 418 419asm ( 420".globl " SYMBOL_STRING(ctiVMThrowTrampoline) "\n" 421HIDE_SYMBOL(ctiVMThrowTrampoline) "\n" 422SYMBOL_STRING(ctiVMThrowTrampoline) ":" "\n" 423 "movq %rsp, %rdi" "\n" 424 "call " LOCAL_REFERENCE(cti_vm_throw) "\n" 425 "int3" "\n" 426); 427 428asm ( 429".globl " SYMBOL_STRING(ctiOpThrowNotCaught) "\n" 430HIDE_SYMBOL(ctiOpThrowNotCaught) "\n" 431SYMBOL_STRING(ctiOpThrowNotCaught) ":" "\n" 432 "addq $0x78, %rsp" "\n" 433 "popq %rbx" "\n" 434 "popq %r15" "\n" 435 "popq %r14" "\n" 436 "popq %r13" "\n" 437 "popq %r12" "\n" 438 "popq %rbp" "\n" 439 "ret" "\n" 440); 441 442#elif COMPILER(GCC) && CPU(X86_64) && OS(WINDOWS) 443 444// These ASSERTs remind you that, if you change the layout of JITStackFrame, you 445// need to change the assembly trampolines below to match. 446COMPILE_ASSERT(offsetof(struct JITStackFrame, code) % 16 == 0x0, JITStackFrame_maintains_16byte_stack_alignment); 447COMPILE_ASSERT(offsetof(struct JITStackFrame, savedRBX) == 0x58, JITStackFrame_stub_argument_space_matches_ctiTrampoline); 448 449asm ( 450".text\n" 451".globl " SYMBOL_STRING(ctiTrampoline) "\n" 452HIDE_SYMBOL(ctiTrampoline) "\n" 453SYMBOL_STRING(ctiTrampoline) ":" "\n" 454 // Dump register parameters to their home address 455 "movq %r9, 0x20(%rsp)" "\n" 456 "movq %r8, 0x18(%rsp)" "\n" 457 "movq %rdx, 0x10(%rsp)" "\n" 458 "movq %rcx, 0x8(%rsp)" "\n" 459 460 "pushq %rbp" "\n" 461 "movq %rsp, %rbp" "\n" 462 "pushq %r12" "\n" 463 "pushq %r13" "\n" 464 "pushq %r14" "\n" 465 "pushq %r15" "\n" 466 "pushq %rbx" "\n" 467 468 // Decrease rsp to point to the start of our JITStackFrame 469 "subq $0x58, %rsp" "\n" 470 "movq $512, %r12" "\n" 471 "movq $0xFFFF000000000000, %r14" "\n" 472 "movq $0xFFFF000000000002, %r15" "\n" 473 "movq %r8, %r13" "\n" 474 "call *%rcx" "\n" 475 "addq $0x58, %rsp" "\n" 476 "popq %rbx" "\n" 477 "popq %r15" "\n" 478 "popq %r14" "\n" 479 "popq %r13" "\n" 480 "popq %r12" "\n" 481 "popq %rbp" "\n" 482 "ret" "\n" 483".globl " SYMBOL_STRING(ctiTrampolineEnd) "\n" 484HIDE_SYMBOL(ctiTrampolineEnd) "\n" 485SYMBOL_STRING(ctiTrampolineEnd) ":" "\n" 486); 487 488asm ( 489".globl " SYMBOL_STRING(ctiVMThrowTrampoline) "\n" 490HIDE_SYMBOL(ctiVMThrowTrampoline) "\n" 491SYMBOL_STRING(ctiVMThrowTrampoline) ":" "\n" 492 "movq %rsp, %rcx" "\n" 493 "call " LOCAL_REFERENCE(cti_vm_throw) "\n" 494 "int3" "\n" 495); 496 497asm ( 498".globl " SYMBOL_STRING(ctiOpThrowNotCaught) "\n" 499HIDE_SYMBOL(ctiOpThrowNotCaught) "\n" 500SYMBOL_STRING(ctiOpThrowNotCaught) ":" "\n" 501 "addq $0x58, %rsp" "\n" 502 "popq %rbx" "\n" 503 "popq %r15" "\n" 504 "popq %r14" "\n" 505 "popq %r13" "\n" 506 "popq %r12" "\n" 507 "popq %rbp" "\n" 508 "ret" "\n" 509); 510 511#elif COMPILER(MSVC) && CPU(X86_64) 512 513// These ASSERTs remind you that, if you change the layout of JITStackFrame, you 514// need to change the assembly trampolines in JITStubsMSVC64.asm to match. 515COMPILE_ASSERT(offsetof(struct JITStackFrame, code) % 16 == 0x0, JITStackFrame_maintains_16byte_stack_alignment); 516COMPILE_ASSERT(offsetof(struct JITStackFrame, savedRBX) == 0x58, JITStackFrame_stub_argument_space_matches_ctiTrampoline); 517 518#else 519 #error "JIT not supported on this platform." 520#endif 521 522#endif // USE(JSVALUE32_64) 523 524#if CPU(MIPS) 525asm ( 526".text" "\n" 527".align 2" "\n" 528".set noreorder" "\n" 529".set nomacro" "\n" 530".set nomips16" "\n" 531".globl " SYMBOL_STRING(ctiTrampoline) "\n" 532".ent " SYMBOL_STRING(ctiTrampoline) "\n" 533SYMBOL_STRING(ctiTrampoline) ":" "\n" 534 "addiu $29,$29,-" STRINGIZE_VALUE_OF(STACK_LENGTH) "\n" 535 "sw $31," STRINGIZE_VALUE_OF(PRESERVED_RETURN_ADDRESS_OFFSET) "($29)" "\n" 536 "sw $20," STRINGIZE_VALUE_OF(PRESERVED_S4_OFFSET) "($29)" "\n" 537 "sw $19," STRINGIZE_VALUE_OF(PRESERVED_S3_OFFSET) "($29)" "\n" 538 "sw $18," STRINGIZE_VALUE_OF(PRESERVED_S2_OFFSET) "($29)" "\n" 539 "sw $17," STRINGIZE_VALUE_OF(PRESERVED_S1_OFFSET) "($29)" "\n" 540 "sw $16," STRINGIZE_VALUE_OF(PRESERVED_S0_OFFSET) "($29)" "\n" 541#if WTF_MIPS_PIC 542 "sw $28," STRINGIZE_VALUE_OF(PRESERVED_GP_OFFSET) "($29)" "\n" 543#endif 544 "move $16,$6 # set callFrameRegister" "\n" 545 "move $25,$4 # move executableAddress to t9" "\n" 546 "sw $5," STRINGIZE_VALUE_OF(REGISTER_FILE_OFFSET) "($29) # store JSStack to current stack" "\n" 547 "lw $9," STRINGIZE_VALUE_OF(STACK_LENGTH + 20) "($29) # load vm from previous stack" "\n" 548 "jalr $25" "\n" 549 "sw $9," STRINGIZE_VALUE_OF(GLOBAL_DATA_OFFSET) "($29) # store vm to current stack" "\n" 550 "lw $16," STRINGIZE_VALUE_OF(PRESERVED_S0_OFFSET) "($29)" "\n" 551 "lw $17," STRINGIZE_VALUE_OF(PRESERVED_S1_OFFSET) "($29)" "\n" 552 "lw $18," STRINGIZE_VALUE_OF(PRESERVED_S2_OFFSET) "($29)" "\n" 553 "lw $19," STRINGIZE_VALUE_OF(PRESERVED_S3_OFFSET) "($29)" "\n" 554 "lw $20," STRINGIZE_VALUE_OF(PRESERVED_S4_OFFSET) "($29)" "\n" 555 "lw $31," STRINGIZE_VALUE_OF(PRESERVED_RETURN_ADDRESS_OFFSET) "($29)" "\n" 556 "jr $31" "\n" 557 "addiu $29,$29," STRINGIZE_VALUE_OF(STACK_LENGTH) "\n" 558".set reorder" "\n" 559".set macro" "\n" 560".end " SYMBOL_STRING(ctiTrampoline) "\n" 561".globl " SYMBOL_STRING(ctiTrampolineEnd) "\n" 562HIDE_SYMBOL(ctiTrampolineEnd) "\n" 563SYMBOL_STRING(ctiTrampolineEnd) ":" "\n" 564); 565 566asm ( 567".text" "\n" 568".align 2" "\n" 569".set noreorder" "\n" 570".set nomacro" "\n" 571".set nomips16" "\n" 572".globl " SYMBOL_STRING(ctiVMThrowTrampoline) "\n" 573".ent " SYMBOL_STRING(ctiVMThrowTrampoline) "\n" 574SYMBOL_STRING(ctiVMThrowTrampoline) ":" "\n" 575#if WTF_MIPS_PIC 576".set macro" "\n" 577".cpload $31" "\n" 578 "la $25," SYMBOL_STRING(cti_vm_throw) "\n" 579".set nomacro" "\n" 580 "bal " SYMBOL_STRING(cti_vm_throw) "\n" 581 "move $4,$29" "\n" 582#else 583 "jal " SYMBOL_STRING(cti_vm_throw) "\n" 584 "move $4,$29" "\n" 585#endif 586 "lw $16," STRINGIZE_VALUE_OF(PRESERVED_S0_OFFSET) "($29)" "\n" 587 "lw $17," STRINGIZE_VALUE_OF(PRESERVED_S1_OFFSET) "($29)" "\n" 588 "lw $18," STRINGIZE_VALUE_OF(PRESERVED_S2_OFFSET) "($29)" "\n" 589 "lw $19," STRINGIZE_VALUE_OF(PRESERVED_S3_OFFSET) "($29)" "\n" 590 "lw $20," STRINGIZE_VALUE_OF(PRESERVED_S4_OFFSET) "($29)" "\n" 591 "lw $31," STRINGIZE_VALUE_OF(PRESERVED_RETURN_ADDRESS_OFFSET) "($29)" "\n" 592 "jr $31" "\n" 593 "addiu $29,$29," STRINGIZE_VALUE_OF(STACK_LENGTH) "\n" 594".set reorder" "\n" 595".set macro" "\n" 596".end " SYMBOL_STRING(ctiVMThrowTrampoline) "\n" 597); 598 599asm ( 600".text" "\n" 601".align 2" "\n" 602".set noreorder" "\n" 603".set nomacro" "\n" 604".set nomips16" "\n" 605".globl " SYMBOL_STRING(ctiOpThrowNotCaught) "\n" 606".ent " SYMBOL_STRING(ctiOpThrowNotCaught) "\n" 607SYMBOL_STRING(ctiOpThrowNotCaught) ":" "\n" 608 "lw $16," STRINGIZE_VALUE_OF(PRESERVED_S0_OFFSET) "($29)" "\n" 609 "lw $17," STRINGIZE_VALUE_OF(PRESERVED_S1_OFFSET) "($29)" "\n" 610 "lw $18," STRINGIZE_VALUE_OF(PRESERVED_S2_OFFSET) "($29)" "\n" 611 "lw $19," STRINGIZE_VALUE_OF(PRESERVED_S3_OFFSET) "($29)" "\n" 612 "lw $20," STRINGIZE_VALUE_OF(PRESERVED_S4_OFFSET) "($29)" "\n" 613 "lw $31," STRINGIZE_VALUE_OF(PRESERVED_RETURN_ADDRESS_OFFSET) "($29)" "\n" 614 "jr $31" "\n" 615 "addiu $29,$29," STRINGIZE_VALUE_OF(STACK_LENGTH) "\n" 616".set reorder" "\n" 617".set macro" "\n" 618".end " SYMBOL_STRING(ctiOpThrowNotCaught) "\n" 619); 620#endif 621 622#if COMPILER(GCC) && CPU(ARM_THUMB2) 623 624asm ( 625".text" "\n" 626".align 2" "\n" 627".globl " SYMBOL_STRING(ctiTrampoline) "\n" 628HIDE_SYMBOL(ctiTrampoline) "\n" 629".thumb" "\n" 630".thumb_func " THUMB_FUNC_PARAM(ctiTrampoline) "\n" 631SYMBOL_STRING(ctiTrampoline) ":" "\n" 632 "sub sp, sp, #" STRINGIZE_VALUE_OF(FIRST_STACK_ARGUMENT) "\n" 633 "str lr, [sp, #" STRINGIZE_VALUE_OF(PRESERVED_RETURN_ADDRESS_OFFSET) "]" "\n" 634 "str r4, [sp, #" STRINGIZE_VALUE_OF(PRESERVED_R4_OFFSET) "]" "\n" 635 "str r5, [sp, #" STRINGIZE_VALUE_OF(PRESERVED_R5_OFFSET) "]" "\n" 636 "str r6, [sp, #" STRINGIZE_VALUE_OF(PRESERVED_R6_OFFSET) "]" "\n" 637 "str r7, [sp, #" STRINGIZE_VALUE_OF(PRESERVED_R7_OFFSET) "]" "\n" 638 "str r8, [sp, #" STRINGIZE_VALUE_OF(PRESERVED_R8_OFFSET) "]" "\n" 639 "str r9, [sp, #" STRINGIZE_VALUE_OF(PRESERVED_R9_OFFSET) "]" "\n" 640 "str r10, [sp, #" STRINGIZE_VALUE_OF(PRESERVED_R10_OFFSET) "]" "\n" 641 "str r11, [sp, #" STRINGIZE_VALUE_OF(PRESERVED_R11_OFFSET) "]" "\n" 642 "str r1, [sp, #" STRINGIZE_VALUE_OF(REGISTER_FILE_OFFSET) "]" "\n" 643 "mov r5, r2" "\n" 644 "mov r6, #512" "\n" 645 "blx r0" "\n" 646 "ldr r11, [sp, #" STRINGIZE_VALUE_OF(PRESERVED_R11_OFFSET) "]" "\n" 647 "ldr r10, [sp, #" STRINGIZE_VALUE_OF(PRESERVED_R10_OFFSET) "]" "\n" 648 "ldr r9, [sp, #" STRINGIZE_VALUE_OF(PRESERVED_R9_OFFSET) "]" "\n" 649 "ldr r8, [sp, #" STRINGIZE_VALUE_OF(PRESERVED_R8_OFFSET) "]" "\n" 650 "ldr r7, [sp, #" STRINGIZE_VALUE_OF(PRESERVED_R7_OFFSET) "]" "\n" 651 "ldr r6, [sp, #" STRINGIZE_VALUE_OF(PRESERVED_R6_OFFSET) "]" "\n" 652 "ldr r5, [sp, #" STRINGIZE_VALUE_OF(PRESERVED_R5_OFFSET) "]" "\n" 653 "ldr r4, [sp, #" STRINGIZE_VALUE_OF(PRESERVED_R4_OFFSET) "]" "\n" 654 "ldr lr, [sp, #" STRINGIZE_VALUE_OF(PRESERVED_RETURN_ADDRESS_OFFSET) "]" "\n" 655 "add sp, sp, #" STRINGIZE_VALUE_OF(FIRST_STACK_ARGUMENT) "\n" 656 "bx lr" "\n" 657".align 2" "\n" 658".globl " SYMBOL_STRING(ctiTrampolineEnd) "\n" 659HIDE_SYMBOL(ctiTrampolineEnd) "\n" 660".thumb" "\n" 661".thumb_func " THUMB_FUNC_PARAM(ctiTrampolineEnd) "\n" 662SYMBOL_STRING(ctiTrampolineEnd) ":" "\n" 663); 664 665asm ( 666".text" "\n" 667".align 2" "\n" 668".globl " SYMBOL_STRING(ctiVMThrowTrampoline) "\n" 669HIDE_SYMBOL(ctiVMThrowTrampoline) "\n" 670".thumb" "\n" 671".thumb_func " THUMB_FUNC_PARAM(ctiVMThrowTrampoline) "\n" 672SYMBOL_STRING(ctiVMThrowTrampoline) ":" "\n" 673 "mov r0, sp" "\n" 674 "bl " LOCAL_REFERENCE(cti_vm_throw) "\n" 675 "ldr r11, [sp, #" STRINGIZE_VALUE_OF(PRESERVED_R11_OFFSET) "]" "\n" 676 "ldr r10, [sp, #" STRINGIZE_VALUE_OF(PRESERVED_R10_OFFSET) "]" "\n" 677 "ldr r9, [sp, #" STRINGIZE_VALUE_OF(PRESERVED_R9_OFFSET) "]" "\n" 678 "ldr r8, [sp, #" STRINGIZE_VALUE_OF(PRESERVED_R8_OFFSET) "]" "\n" 679 "ldr r7, [sp, #" STRINGIZE_VALUE_OF(PRESERVED_R7_OFFSET) "]" "\n" 680 "ldr r6, [sp, #" STRINGIZE_VALUE_OF(PRESERVED_R6_OFFSET) "]" "\n" 681 "ldr r5, [sp, #" STRINGIZE_VALUE_OF(PRESERVED_R5_OFFSET) "]" "\n" 682 "ldr r4, [sp, #" STRINGIZE_VALUE_OF(PRESERVED_R4_OFFSET) "]" "\n" 683 "ldr lr, [sp, #" STRINGIZE_VALUE_OF(PRESERVED_RETURN_ADDRESS_OFFSET) "]" "\n" 684 "add sp, sp, #" STRINGIZE_VALUE_OF(FIRST_STACK_ARGUMENT) "\n" 685 "bx lr" "\n" 686); 687 688asm ( 689".text" "\n" 690".align 2" "\n" 691".globl " SYMBOL_STRING(ctiOpThrowNotCaught) "\n" 692HIDE_SYMBOL(ctiOpThrowNotCaught) "\n" 693".thumb" "\n" 694".thumb_func " THUMB_FUNC_PARAM(ctiOpThrowNotCaught) "\n" 695SYMBOL_STRING(ctiOpThrowNotCaught) ":" "\n" 696 "ldr r11, [sp, #" STRINGIZE_VALUE_OF(PRESERVED_R11_OFFSET) "]" "\n" 697 "ldr r10, [sp, #" STRINGIZE_VALUE_OF(PRESERVED_R10_OFFSET) "]" "\n" 698 "ldr r9, [sp, #" STRINGIZE_VALUE_OF(PRESERVED_R9_OFFSET) "]" "\n" 699 "ldr r8, [sp, #" STRINGIZE_VALUE_OF(PRESERVED_R8_OFFSET) "]" "\n" 700 "ldr r7, [sp, #" STRINGIZE_VALUE_OF(PRESERVED_R7_OFFSET) "]" "\n" 701 "ldr r6, [sp, #" STRINGIZE_VALUE_OF(PRESERVED_R6_OFFSET) "]" "\n" 702 "ldr r5, [sp, #" STRINGIZE_VALUE_OF(PRESERVED_R5_OFFSET) "]" "\n" 703 "ldr r4, [sp, #" STRINGIZE_VALUE_OF(PRESERVED_R4_OFFSET) "]" "\n" 704 "ldr lr, [sp, #" STRINGIZE_VALUE_OF(PRESERVED_RETURN_ADDRESS_OFFSET) "]" "\n" 705 "add sp, sp, #" STRINGIZE_VALUE_OF(FIRST_STACK_ARGUMENT) "\n" 706 "bx lr" "\n" 707); 708 709#elif COMPILER(GCC) && CPU(ARM_TRADITIONAL) 710 711asm ( 712".text" "\n" 713".globl " SYMBOL_STRING(ctiTrampoline) "\n" 714HIDE_SYMBOL(ctiTrampoline) "\n" 715INLINE_ARM_FUNCTION(ctiTrampoline) 716SYMBOL_STRING(ctiTrampoline) ":" "\n" 717 "stmdb sp!, {r1-r3}" "\n" 718 "stmdb sp!, {r4-r6, r8-r11, lr}" "\n" 719 "sub sp, sp, #" STRINGIZE_VALUE_OF(PRESERVEDR4_OFFSET) "\n" 720 "mov r5, r2" "\n" 721 "mov r6, #512" "\n" 722 // r0 contains the code 723 "blx r0" "\n" 724 "add sp, sp, #" STRINGIZE_VALUE_OF(PRESERVEDR4_OFFSET) "\n" 725 "ldmia sp!, {r4-r6, r8-r11, lr}" "\n" 726 "add sp, sp, #12" "\n" 727 "bx lr" "\n" 728".globl " SYMBOL_STRING(ctiTrampolineEnd) "\n" 729HIDE_SYMBOL(ctiTrampolineEnd) "\n" 730SYMBOL_STRING(ctiTrampolineEnd) ":" "\n" 731); 732 733asm ( 734".text" "\n" 735".globl " SYMBOL_STRING(ctiVMThrowTrampoline) "\n" 736HIDE_SYMBOL(ctiVMThrowTrampoline) "\n" 737INLINE_ARM_FUNCTION(ctiVMThrowTrampoline) 738SYMBOL_STRING(ctiVMThrowTrampoline) ":" "\n" 739 "mov r0, sp" "\n" 740 "bl " SYMBOL_STRING(cti_vm_throw) "\n" 741 742// Both has the same return sequence 743".text" "\n" 744".globl " SYMBOL_STRING(ctiOpThrowNotCaught) "\n" 745HIDE_SYMBOL(ctiOpThrowNotCaught) "\n" 746INLINE_ARM_FUNCTION(ctiOpThrowNotCaught) 747SYMBOL_STRING(ctiOpThrowNotCaught) ":" "\n" 748 "add sp, sp, #" STRINGIZE_VALUE_OF(PRESERVEDR4_OFFSET) "\n" 749 "ldmia sp!, {r4-r6, r8-r11, lr}" "\n" 750 "add sp, sp, #12" "\n" 751 "bx lr" "\n" 752); 753 754#elif COMPILER(RVCT) && CPU(ARM_THUMB2) 755 756__asm EncodedJSValue ctiTrampoline(void*, JSStack*, CallFrame*, void* /*unused1*/, void* /*unused2*/, VM*) 757{ 758 PRESERVE8 759 sub sp, sp, # FIRST_STACK_ARGUMENT 760 str lr, [sp, # PRESERVED_RETURN_ADDRESS_OFFSET ] 761 str r4, [sp, # PRESERVED_R4_OFFSET ] 762 str r5, [sp, # PRESERVED_R5_OFFSET ] 763 str r6, [sp, # PRESERVED_R6_OFFSET ] 764 str r7, [sp, # PRESERVED_R7_OFFSET ] 765 str r8, [sp, # PRESERVED_R8_OFFSET ] 766 str r9, [sp, # PRESERVED_R9_OFFSET ] 767 str r10, [sp, # PRESERVED_R10_OFFSET ] 768 str r11, [sp, # PRESERVED_R11_OFFSET ] 769 str r1, [sp, # REGISTER_FILE_OFFSET ] 770 mov r5, r2 771 mov r6, #512 772 blx r0 773 ldr r11, [sp, # PRESERVED_R11_OFFSET ] 774 ldr r10, [sp, # PRESERVED_R10_OFFSET ] 775 ldr r9, [sp, # PRESERVED_R9_OFFSET ] 776 ldr r8, [sp, # PRESERVED_R8_OFFSET ] 777 ldr r7, [sp, # PRESERVED_R7_OFFSET ] 778 ldr r6, [sp, # PRESERVED_R6_OFFSET ] 779 ldr r5, [sp, # PRESERVED_R5_OFFSET ] 780 ldr r4, [sp, # PRESERVED_R4_OFFSET ] 781 ldr lr, [sp, # PRESERVED_RETURN_ADDRESS_OFFSET ] 782 add sp, sp, # FIRST_STACK_ARGUMENT 783 bx lr 784} 785 786__asm void ctiVMThrowTrampoline() 787{ 788 PRESERVE8 789 mov r0, sp 790 bl cti_vm_throw 791 ldr r11, [sp, # PRESERVED_R11_OFFSET ] 792 ldr r10, [sp, # PRESERVED_R10_OFFSET ] 793 ldr r9, [sp, # PRESERVED_R9_OFFSET ] 794 ldr r8, [sp, # PRESERVED_R8_OFFSET ] 795 ldr r7, [sp, # PRESERVED_R7_OFFSET ] 796 ldr r6, [sp, # PRESERVED_R6_OFFSET ] 797 ldr r6, [sp, # PRESERVED_R6_OFFSET ] 798 ldr r5, [sp, # PRESERVED_R5_OFFSET ] 799 ldr r4, [sp, # PRESERVED_R4_OFFSET ] 800 ldr lr, [sp, # PRESERVED_RETURN_ADDRESS_OFFSET ] 801 add sp, sp, # FIRST_STACK_ARGUMENT 802 bx lr 803} 804 805__asm void ctiOpThrowNotCaught() 806{ 807 PRESERVE8 808 ldr r11, [sp, # PRESERVED_R11_OFFSET ] 809 ldr r10, [sp, # PRESERVED_R10_OFFSET ] 810 ldr r9, [sp, # PRESERVED_R9_OFFSET ] 811 ldr r8, [sp, # PRESERVED_R8_OFFSET ] 812 ldr r7, [sp, # PRESERVED_R7_OFFSET ] 813 ldr r6, [sp, # PRESERVED_R6_OFFSET ] 814 ldr r6, [sp, # PRESERVED_R6_OFFSET ] 815 ldr r5, [sp, # PRESERVED_R5_OFFSET ] 816 ldr r4, [sp, # PRESERVED_R4_OFFSET ] 817 ldr lr, [sp, # PRESERVED_RETURN_ADDRESS_OFFSET ] 818 add sp, sp, # FIRST_STACK_ARGUMENT 819 bx lr 820} 821 822#elif COMPILER(RVCT) && CPU(ARM_TRADITIONAL) 823 824__asm EncodedJSValue ctiTrampoline(void*, JSStack*, CallFrame*, void* /*unused1*/, void* /*unused2*/, VM*) 825{ 826 ARM 827 stmdb sp!, {r1-r3} 828 stmdb sp!, {r4-r6, r8-r11, lr} 829 sub sp, sp, # PRESERVEDR4_OFFSET 830 mov r5, r2 831 mov r6, #512 832 mov lr, pc 833 bx r0 834 add sp, sp, # PRESERVEDR4_OFFSET 835 ldmia sp!, {r4-r6, r8-r11, lr} 836 add sp, sp, #12 837 bx lr 838} 839__asm void ctiTrampolineEnd() 840{ 841} 842 843__asm void ctiVMThrowTrampoline() 844{ 845 ARM 846 PRESERVE8 847 mov r0, sp 848 bl cti_vm_throw 849 add sp, sp, # PRESERVEDR4_OFFSET 850 ldmia sp!, {r4-r6, r8-r11, lr} 851 add sp, sp, #12 852 bx lr 853} 854 855__asm void ctiOpThrowNotCaught() 856{ 857 ARM 858 add sp, sp, # PRESERVEDR4_OFFSET 859 ldmia sp!, {r4-r8, lr} 860 add sp, sp, #12 861 bx lr 862} 863#endif 864 865#if ENABLE(OPCODE_SAMPLING) 866 #define CTI_SAMPLER stackFrame.vm->interpreter->sampler() 867#else 868 #define CTI_SAMPLER 0 869#endif 870 871void performPlatformSpecificJITAssertions(VM* vm) 872{ 873 if (!vm->canUseJIT()) 874 return; 875 876#if CPU(ARM_THUMB2) 877 // Unfortunate the arm compiler does not like the use of offsetof on JITStackFrame (since it contains non POD types), 878 // and the OBJECT_OFFSETOF macro does not appear constantish enough for it to be happy with its use in COMPILE_ASSERT 879 // macros. 880 ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, preservedReturnAddress) == PRESERVED_RETURN_ADDRESS_OFFSET); 881 ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, preservedR4) == PRESERVED_R4_OFFSET); 882 ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, preservedR5) == PRESERVED_R5_OFFSET); 883 ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, preservedR6) == PRESERVED_R6_OFFSET); 884 ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, preservedR7) == PRESERVED_R7_OFFSET); 885 ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, preservedR8) == PRESERVED_R8_OFFSET); 886 ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, preservedR9) == PRESERVED_R9_OFFSET); 887 ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, preservedR10) == PRESERVED_R10_OFFSET); 888 ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, preservedR11) == PRESERVED_R11_OFFSET); 889 890 ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, stack) == REGISTER_FILE_OFFSET); 891 // The fifth argument is the first item already on the stack. 892 ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, unused1) == FIRST_STACK_ARGUMENT); 893 894 ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, thunkReturnAddress) == THUNK_RETURN_ADDRESS_OFFSET); 895 896#elif CPU(ARM_TRADITIONAL) 897 898 ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, thunkReturnAddress) == THUNK_RETURN_ADDRESS_OFFSET); 899 ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, preservedR4) == PRESERVEDR4_OFFSET); 900 901 902#elif CPU(MIPS) 903 ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, preservedGP) == PRESERVED_GP_OFFSET); 904 ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, preservedS0) == PRESERVED_S0_OFFSET); 905 ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, preservedS1) == PRESERVED_S1_OFFSET); 906 ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, preservedS2) == PRESERVED_S2_OFFSET); 907 ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, preservedReturnAddress) == PRESERVED_RETURN_ADDRESS_OFFSET); 908 ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, thunkReturnAddress) == THUNK_RETURN_ADDRESS_OFFSET); 909 ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, stack) == REGISTER_FILE_OFFSET); 910 ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, vm) == GLOBAL_DATA_OFFSET); 911 912#endif 913} 914 915NEVER_INLINE static void tryCachePutByID(CallFrame* callFrame, CodeBlock* codeBlock, ReturnAddressPtr returnAddress, JSValue baseValue, const PutPropertySlot& slot, StructureStubInfo* stubInfo, bool direct) 916{ 917 // The interpreter checks for recursion here; I do not believe this can occur in CTI. 918 919 if (!baseValue.isCell()) 920 return; 921 922 // Uncacheable: give up. 923 if (!slot.isCacheable()) { 924 ctiPatchCallByReturnAddress(codeBlock, returnAddress, FunctionPtr(direct ? cti_op_put_by_id_direct_generic : cti_op_put_by_id_generic)); 925 return; 926 } 927 928 JSCell* baseCell = baseValue.asCell(); 929 Structure* structure = baseCell->structure(); 930 931 if (structure->isUncacheableDictionary() || structure->typeInfo().prohibitsPropertyCaching()) { 932 ctiPatchCallByReturnAddress(codeBlock, returnAddress, FunctionPtr(direct ? cti_op_put_by_id_direct_generic : cti_op_put_by_id_generic)); 933 return; 934 } 935 936 // If baseCell != base, then baseCell must be a proxy for another object. 937 if (baseCell != slot.base()) { 938 ctiPatchCallByReturnAddress(codeBlock, returnAddress, FunctionPtr(direct ? cti_op_put_by_id_direct_generic : cti_op_put_by_id_generic)); 939 return; 940 } 941 942 // Cache hit: Specialize instruction and ref Structures. 943 944 // Structure transition, cache transition info 945 if (slot.type() == PutPropertySlot::NewProperty) { 946 if (structure->isDictionary()) { 947 ctiPatchCallByReturnAddress(codeBlock, returnAddress, FunctionPtr(direct ? cti_op_put_by_id_direct_generic : cti_op_put_by_id_generic)); 948 return; 949 } 950 951 // put_by_id_transition checks the prototype chain for setters. 952 if (normalizePrototypeChain(callFrame, baseCell) == InvalidPrototypeChain) { 953 ctiPatchCallByReturnAddress(codeBlock, returnAddress, FunctionPtr(direct ? cti_op_put_by_id_direct_generic : cti_op_put_by_id_generic)); 954 return; 955 } 956 957 StructureChain* prototypeChain = structure->prototypeChain(callFrame); 958 ASSERT(structure->previousID()->transitionWatchpointSetHasBeenInvalidated()); 959 stubInfo->initPutByIdTransition(callFrame->vm(), codeBlock->ownerExecutable(), structure->previousID(), structure, prototypeChain, direct); 960 JIT::compilePutByIdTransition(callFrame->scope()->vm(), codeBlock, stubInfo, structure->previousID(), structure, slot.cachedOffset(), prototypeChain, returnAddress, direct); 961 return; 962 } 963 964 stubInfo->initPutByIdReplace(callFrame->vm(), codeBlock->ownerExecutable(), structure); 965 966 JIT::patchPutByIdReplace(codeBlock, stubInfo, structure, slot.cachedOffset(), returnAddress, direct); 967} 968 969NEVER_INLINE static void tryCacheGetByID(CallFrame* callFrame, CodeBlock* codeBlock, ReturnAddressPtr returnAddress, JSValue baseValue, const Identifier& propertyName, const PropertySlot& slot, StructureStubInfo* stubInfo) 970{ 971 // FIXME: Write a test that proves we need to check for recursion here just 972 // like the interpreter does, then add a check for recursion. 973 974 // FIXME: Cache property access for immediates. 975 if (!baseValue.isCell()) { 976 ctiPatchCallByReturnAddress(codeBlock, returnAddress, FunctionPtr(cti_op_get_by_id_generic)); 977 return; 978 } 979 980 VM* vm = &callFrame->vm(); 981 982 if (isJSArray(baseValue) && propertyName == callFrame->propertyNames().length) { 983 JIT::compilePatchGetArrayLength(callFrame->scope()->vm(), codeBlock, returnAddress); 984 return; 985 } 986 987 if (isJSString(baseValue) && propertyName == callFrame->propertyNames().length) { 988 // The tradeoff of compiling an patched inline string length access routine does not seem 989 // to pay off, so we currently only do this for arrays. 990 ctiPatchCallByReturnAddress(codeBlock, returnAddress, vm->getCTIStub(stringLengthTrampolineGenerator).code()); 991 return; 992 } 993 994 // Uncacheable: give up. 995 if (!slot.isCacheable()) { 996 stubInfo->accessType = access_get_by_id_generic; 997 ctiPatchCallByReturnAddress(codeBlock, returnAddress, FunctionPtr(cti_op_get_by_id_generic)); 998 return; 999 } 1000 1001 JSCell* baseCell = baseValue.asCell(); 1002 Structure* structure = baseCell->structure(); 1003 1004 if (structure->isUncacheableDictionary() || structure->typeInfo().prohibitsPropertyCaching()) { 1005 stubInfo->accessType = access_get_by_id_generic; 1006 ctiPatchCallByReturnAddress(codeBlock, returnAddress, FunctionPtr(cti_op_get_by_id_generic)); 1007 return; 1008 } 1009 1010 // Cache hit: Specialize instruction and ref Structures. 1011 1012 if (slot.slotBase() == baseValue) { 1013 RELEASE_ASSERT(stubInfo->accessType == access_unset); 1014 if ((slot.cachedPropertyType() != PropertySlot::Value) 1015 || !MacroAssembler::isCompactPtrAlignedAddressOffset(maxOffsetRelativeToPatchedStorage(slot.cachedOffset()))) 1016 ctiPatchCallByReturnAddress(codeBlock, returnAddress, FunctionPtr(cti_op_get_by_id_self_fail)); 1017 else { 1018 JIT::patchGetByIdSelf(codeBlock, stubInfo, structure, slot.cachedOffset(), returnAddress); 1019 stubInfo->initGetByIdSelf(callFrame->vm(), codeBlock->ownerExecutable(), structure); 1020 } 1021 return; 1022 } 1023 1024 if (structure->isDictionary()) { 1025 stubInfo->accessType = access_get_by_id_generic; 1026 ctiPatchCallByReturnAddress(codeBlock, returnAddress, FunctionPtr(cti_op_get_by_id_generic)); 1027 return; 1028 } 1029 1030 if (slot.slotBase() == structure->prototypeForLookup(callFrame)) { 1031 ASSERT(slot.slotBase().isObject()); 1032 1033 JSObject* slotBaseObject = asObject(slot.slotBase()); 1034 size_t offset = slot.cachedOffset(); 1035 1036 if (structure->typeInfo().hasImpureGetOwnPropertySlot()) { 1037 stubInfo->accessType = access_get_by_id_generic; 1038 ctiPatchCallByReturnAddress(codeBlock, returnAddress, FunctionPtr(cti_op_get_by_id_generic)); 1039 return; 1040 } 1041 1042 // Since we're accessing a prototype in a loop, it's a good bet that it 1043 // should not be treated as a dictionary. 1044 if (slotBaseObject->structure()->isDictionary()) { 1045 slotBaseObject->flattenDictionaryObject(callFrame->vm()); 1046 offset = slotBaseObject->structure()->get(callFrame->vm(), propertyName); 1047 } 1048 1049 stubInfo->initGetByIdProto(callFrame->vm(), codeBlock->ownerExecutable(), structure, slotBaseObject->structure(), slot.cachedPropertyType() == PropertySlot::Value); 1050 1051 ASSERT(!structure->isDictionary()); 1052 ASSERT(!slotBaseObject->structure()->isDictionary()); 1053 JIT::compileGetByIdProto(callFrame->scope()->vm(), callFrame, codeBlock, stubInfo, structure, slotBaseObject->structure(), propertyName, slot, offset, returnAddress); 1054 return; 1055 } 1056 1057 PropertyOffset offset = slot.cachedOffset(); 1058 size_t count = normalizePrototypeChainForChainAccess(callFrame, baseValue, slot.slotBase(), propertyName, offset); 1059 if (count == InvalidPrototypeChain) { 1060 stubInfo->accessType = access_get_by_id_generic; 1061 ctiPatchCallByReturnAddress(codeBlock, returnAddress, FunctionPtr(cti_op_get_by_id_generic)); 1062 return; 1063 } 1064 1065 StructureChain* prototypeChain = structure->prototypeChain(callFrame); 1066 stubInfo->initGetByIdChain(callFrame->vm(), codeBlock->ownerExecutable(), structure, prototypeChain, count, slot.cachedPropertyType() == PropertySlot::Value); 1067 JIT::compileGetByIdChain(callFrame->scope()->vm(), callFrame, codeBlock, stubInfo, structure, prototypeChain, count, propertyName, slot, offset, returnAddress); 1068} 1069 1070#if !defined(NDEBUG) 1071 1072extern "C" { 1073 1074static void jscGeneratedNativeCode() 1075{ 1076 // When executing a JIT stub function (which might do an allocation), we hack the return address 1077 // to pretend to be executing this function, to keep stack logging tools from blowing out 1078 // memory. 1079} 1080 1081} 1082 1083struct StackHack { 1084 ALWAYS_INLINE StackHack(JITStackFrame& stackFrame) 1085 : stackFrame(stackFrame) 1086 , savedReturnAddress(*stackFrame.returnAddressSlot()) 1087 { 1088 if (!CodeProfiling::enabled()) 1089 *stackFrame.returnAddressSlot() = ReturnAddressPtr(FunctionPtr(jscGeneratedNativeCode)); 1090 } 1091 1092 ALWAYS_INLINE ~StackHack() 1093 { 1094 *stackFrame.returnAddressSlot() = savedReturnAddress; 1095 } 1096 1097 JITStackFrame& stackFrame; 1098 ReturnAddressPtr savedReturnAddress; 1099}; 1100 1101#define STUB_INIT_STACK_FRAME(stackFrame) JITStackFrame& stackFrame = *reinterpret_cast_ptr<JITStackFrame*>(STUB_ARGS); StackHack stackHack(stackFrame) 1102#define STUB_SET_RETURN_ADDRESS(returnAddress) stackHack.savedReturnAddress = ReturnAddressPtr(returnAddress) 1103#define STUB_RETURN_ADDRESS stackHack.savedReturnAddress 1104 1105#else 1106 1107#define STUB_INIT_STACK_FRAME(stackFrame) JITStackFrame& stackFrame = *reinterpret_cast_ptr<JITStackFrame*>(STUB_ARGS) 1108#define STUB_SET_RETURN_ADDRESS(returnAddress) *stackFrame.returnAddressSlot() = ReturnAddressPtr(returnAddress) 1109#define STUB_RETURN_ADDRESS *stackFrame.returnAddressSlot() 1110 1111#endif 1112 1113// The reason this is not inlined is to avoid having to do a PIC branch 1114// to get the address of the ctiVMThrowTrampoline function. It's also 1115// good to keep the code size down by leaving as much of the exception 1116// handling code out of line as possible. 1117static NEVER_INLINE void returnToThrowTrampoline(VM* vm, ReturnAddressPtr exceptionLocation, ReturnAddressPtr& returnAddressSlot) 1118{ 1119 RELEASE_ASSERT(vm->exception); 1120 vm->exceptionLocation = exceptionLocation; 1121 returnAddressSlot = ReturnAddressPtr(FunctionPtr(ctiVMThrowTrampoline)); 1122} 1123 1124#define VM_THROW_EXCEPTION() \ 1125 do { \ 1126 VM_THROW_EXCEPTION_AT_END(); \ 1127 return 0; \ 1128 } while (0) 1129#define VM_THROW_EXCEPTION_AT_END() \ 1130 do {\ 1131 returnToThrowTrampoline(stackFrame.vm, STUB_RETURN_ADDRESS, STUB_RETURN_ADDRESS);\ 1132 } while (0) 1133 1134#define CHECK_FOR_EXCEPTION() \ 1135 do { \ 1136 if (UNLIKELY(stackFrame.vm->exception)) \ 1137 VM_THROW_EXCEPTION(); \ 1138 } while (0) 1139#define CHECK_FOR_EXCEPTION_AT_END() \ 1140 do { \ 1141 if (UNLIKELY(stackFrame.vm->exception)) \ 1142 VM_THROW_EXCEPTION_AT_END(); \ 1143 } while (0) 1144#define CHECK_FOR_EXCEPTION_VOID() \ 1145 do { \ 1146 if (UNLIKELY(stackFrame.vm->exception)) { \ 1147 VM_THROW_EXCEPTION_AT_END(); \ 1148 return; \ 1149 } \ 1150 } while (0) 1151 1152// Helper function for JIT stubs that may throw an exception in the middle of 1153// processing a function call. This function rolls back the stack to 1154// our caller, so exception processing can proceed from a valid state. 1155template<typename T> static T throwExceptionFromOpCall(JITStackFrame& jitStackFrame, CallFrame* newCallFrame, ReturnAddressPtr& returnAddressSlot) 1156{ 1157 CallFrame* callFrame = newCallFrame->callerFrame(); 1158 ASSERT(callFrame->vm().exception); 1159 jitStackFrame.callFrame = callFrame; 1160 callFrame->vm().topCallFrame = callFrame; 1161 returnToThrowTrampoline(&callFrame->vm(), ReturnAddressPtr(newCallFrame->returnPC()), returnAddressSlot); 1162 return T(); 1163} 1164 1165template<typename T> static T throwExceptionFromOpCall(JITStackFrame& jitStackFrame, CallFrame* newCallFrame, ReturnAddressPtr& returnAddressSlot, JSValue exception) 1166{ 1167 newCallFrame->callerFrame()->vm().exception = exception; 1168 return throwExceptionFromOpCall<T>(jitStackFrame, newCallFrame, returnAddressSlot); 1169} 1170 1171#if CPU(ARM_THUMB2) && COMPILER(GCC) 1172 1173#define DEFINE_STUB_FUNCTION(rtype, op) \ 1174 extern "C" { \ 1175 rtype JITStubThunked_##op(STUB_ARGS_DECLARATION); \ 1176 }; \ 1177 asm ( \ 1178 ".text" "\n" \ 1179 ".align 2" "\n" \ 1180 ".globl " SYMBOL_STRING(cti_##op) "\n" \ 1181 HIDE_SYMBOL(cti_##op) "\n" \ 1182 ".thumb" "\n" \ 1183 ".thumb_func " THUMB_FUNC_PARAM(cti_##op) "\n" \ 1184 SYMBOL_STRING(cti_##op) ":" "\n" \ 1185 "str lr, [sp, #" STRINGIZE_VALUE_OF(THUNK_RETURN_ADDRESS_OFFSET) "]" "\n" \ 1186 "bl " SYMBOL_STRING(JITStubThunked_##op) "\n" \ 1187 "ldr lr, [sp, #" STRINGIZE_VALUE_OF(THUNK_RETURN_ADDRESS_OFFSET) "]" "\n" \ 1188 "bx lr" "\n" \ 1189 ); \ 1190 rtype JITStubThunked_##op(STUB_ARGS_DECLARATION) \ 1191 1192#elif CPU(MIPS) 1193#if WTF_MIPS_PIC 1194#define DEFINE_STUB_FUNCTION(rtype, op) \ 1195 extern "C" { \ 1196 rtype JITStubThunked_##op(STUB_ARGS_DECLARATION); \ 1197 }; \ 1198 asm ( \ 1199 ".text" "\n" \ 1200 ".align 2" "\n" \ 1201 ".set noreorder" "\n" \ 1202 ".set nomacro" "\n" \ 1203 ".set nomips16" "\n" \ 1204 ".globl " SYMBOL_STRING(cti_##op) "\n" \ 1205 ".ent " SYMBOL_STRING(cti_##op) "\n" \ 1206 SYMBOL_STRING(cti_##op) ":" "\n" \ 1207 ".set macro" "\n" \ 1208 ".cpload $25" "\n" \ 1209 "sw $31," STRINGIZE_VALUE_OF(THUNK_RETURN_ADDRESS_OFFSET) "($29)" "\n" \ 1210 "la $25," SYMBOL_STRING(JITStubThunked_##op) "\n" \ 1211 ".set nomacro" "\n" \ 1212 ".reloc 1f,R_MIPS_JALR," SYMBOL_STRING(JITStubThunked_##op) "\n" \ 1213 "1: jalr $25" "\n" \ 1214 "nop" "\n" \ 1215 "lw $31," STRINGIZE_VALUE_OF(THUNK_RETURN_ADDRESS_OFFSET) "($29)" "\n" \ 1216 "jr $31" "\n" \ 1217 "nop" "\n" \ 1218 ".set reorder" "\n" \ 1219 ".set macro" "\n" \ 1220 ".end " SYMBOL_STRING(cti_##op) "\n" \ 1221 ); \ 1222 rtype JITStubThunked_##op(STUB_ARGS_DECLARATION) 1223 1224#else // WTF_MIPS_PIC 1225#define DEFINE_STUB_FUNCTION(rtype, op) \ 1226 extern "C" { \ 1227 rtype JITStubThunked_##op(STUB_ARGS_DECLARATION); \ 1228 }; \ 1229 asm ( \ 1230 ".text" "\n" \ 1231 ".align 2" "\n" \ 1232 ".set noreorder" "\n" \ 1233 ".set nomacro" "\n" \ 1234 ".set nomips16" "\n" \ 1235 ".globl " SYMBOL_STRING(cti_##op) "\n" \ 1236 ".ent " SYMBOL_STRING(cti_##op) "\n" \ 1237 SYMBOL_STRING(cti_##op) ":" "\n" \ 1238 "sw $31," STRINGIZE_VALUE_OF(THUNK_RETURN_ADDRESS_OFFSET) "($29)" "\n" \ 1239 "jal " SYMBOL_STRING(JITStubThunked_##op) "\n" \ 1240 "nop" "\n" \ 1241 "lw $31," STRINGIZE_VALUE_OF(THUNK_RETURN_ADDRESS_OFFSET) "($29)" "\n" \ 1242 "jr $31" "\n" \ 1243 "nop" "\n" \ 1244 ".set reorder" "\n" \ 1245 ".set macro" "\n" \ 1246 ".end " SYMBOL_STRING(cti_##op) "\n" \ 1247 ); \ 1248 rtype JITStubThunked_##op(STUB_ARGS_DECLARATION) 1249 1250#endif 1251 1252#elif CPU(ARM_TRADITIONAL) && COMPILER(GCC) 1253 1254#define DEFINE_STUB_FUNCTION(rtype, op) \ 1255 extern "C" { \ 1256 rtype JITStubThunked_##op(STUB_ARGS_DECLARATION); \ 1257 }; \ 1258 asm ( \ 1259 ".globl " SYMBOL_STRING(cti_##op) "\n" \ 1260 INLINE_ARM_FUNCTION(cti_##op) \ 1261 SYMBOL_STRING(cti_##op) ":" "\n" \ 1262 "str lr, [sp, #" STRINGIZE_VALUE_OF(THUNK_RETURN_ADDRESS_OFFSET) "]" "\n" \ 1263 "bl " SYMBOL_STRING(JITStubThunked_##op) "\n" \ 1264 "ldr lr, [sp, #" STRINGIZE_VALUE_OF(THUNK_RETURN_ADDRESS_OFFSET) "]" "\n" \ 1265 "bx lr" "\n" \ 1266 ); \ 1267 rtype JITStubThunked_##op(STUB_ARGS_DECLARATION) 1268 1269#elif (CPU(ARM_THUMB2) || CPU(ARM_TRADITIONAL)) && COMPILER(RVCT) 1270 1271#define DEFINE_STUB_FUNCTION(rtype, op) rtype JITStubThunked_##op(STUB_ARGS_DECLARATION) 1272 1273/* The following is a workaround for RVCT toolchain; precompiler macros are not expanded before the code is passed to the assembler */ 1274 1275/* The following section is a template to generate code for GeneratedJITStubs_RVCT.h */ 1276/* The pattern "#xxx#" will be replaced with "xxx" */ 1277 1278/* 1279RVCT(extern "C" #rtype# JITStubThunked_#op#(STUB_ARGS_DECLARATION);) 1280RVCT(__asm #rtype# cti_#op#(STUB_ARGS_DECLARATION)) 1281RVCT({) 1282RVCT( PRESERVE8) 1283RVCT( IMPORT JITStubThunked_#op#) 1284RVCT( str lr, [sp, # THUNK_RETURN_ADDRESS_OFFSET]) 1285RVCT( bl JITStubThunked_#op#) 1286RVCT( ldr lr, [sp, # THUNK_RETURN_ADDRESS_OFFSET]) 1287RVCT( bx lr) 1288RVCT(}) 1289RVCT() 1290*/ 1291 1292/* Include the generated file */ 1293#include "GeneratedJITStubs_RVCT.h" 1294 1295#elif CPU(ARM_TRADITIONAL) && COMPILER(MSVC) 1296 1297#define DEFINE_STUB_FUNCTION(rtype, op) extern "C" rtype JITStubThunked_##op(STUB_ARGS_DECLARATION) 1298 1299/* The following is a workaround for MSVC toolchain; inline assembler is not supported */ 1300 1301/* The following section is a template to generate code for GeneratedJITStubs_MSVC.asm */ 1302/* The pattern "#xxx#" will be replaced with "xxx" */ 1303 1304/* 1305MSVC_BEGIN( AREA Trampoline, CODE) 1306MSVC_BEGIN() 1307MSVC_BEGIN( EXPORT ctiTrampoline) 1308MSVC_BEGIN( EXPORT ctiTrampolineEnd) 1309MSVC_BEGIN( EXPORT ctiVMThrowTrampoline) 1310MSVC_BEGIN( EXPORT ctiOpThrowNotCaught) 1311MSVC_BEGIN() 1312MSVC_BEGIN(ctiTrampoline PROC) 1313MSVC_BEGIN( stmdb sp!, {r1-r3}) 1314MSVC_BEGIN( stmdb sp!, {r4-r6, r8-r11, lr}) 1315MSVC_BEGIN( sub sp, sp, #68 ; sync with PRESERVEDR4_OFFSET) 1316MSVC_BEGIN( mov r5, r2) 1317MSVC_BEGIN( mov r6, #512) 1318MSVC_BEGIN( ; r0 contains the code) 1319MSVC_BEGIN( mov lr, pc) 1320MSVC_BEGIN( bx r0) 1321MSVC_BEGIN( add sp, sp, #68 ; sync with PRESERVEDR4_OFFSET) 1322MSVC_BEGIN( ldmia sp!, {r4-r6, r8-r11, lr}) 1323MSVC_BEGIN( add sp, sp, #12) 1324MSVC_BEGIN( bx lr) 1325MSVC_BEGIN(ctiTrampolineEnd) 1326MSVC_BEGIN(ctiTrampoline ENDP) 1327MSVC_BEGIN() 1328MSVC_BEGIN(ctiVMThrowTrampoline PROC) 1329MSVC_BEGIN( mov r0, sp) 1330MSVC_BEGIN( bl cti_vm_throw) 1331MSVC_BEGIN(ctiOpThrowNotCaught) 1332MSVC_BEGIN( add sp, sp, #68 ; sync with PRESERVEDR4_OFFSET) 1333MSVC_BEGIN( ldmia sp!, {r4-r6, r8-r11, lr}) 1334MSVC_BEGIN( add sp, sp, #12) 1335MSVC_BEGIN( bx lr) 1336MSVC_BEGIN(ctiVMThrowTrampoline ENDP) 1337MSVC_BEGIN() 1338 1339MSVC( EXPORT cti_#op#) 1340MSVC( IMPORT JITStubThunked_#op#) 1341MSVC(cti_#op# PROC) 1342MSVC( str lr, [sp, #64] ; sync with THUNK_RETURN_ADDRESS_OFFSET) 1343MSVC( bl JITStubThunked_#op#) 1344MSVC( ldr lr, [sp, #64] ; sync with THUNK_RETURN_ADDRESS_OFFSET) 1345MSVC( bx lr) 1346MSVC(cti_#op# ENDP) 1347MSVC() 1348 1349MSVC_END( END) 1350*/ 1351 1352#elif CPU(SH4) 1353#define DEFINE_STUB_FUNCTION(rtype, op) \ 1354 extern "C" { \ 1355 rtype JITStubThunked_##op(STUB_ARGS_DECLARATION); \ 1356 }; \ 1357 asm volatile( \ 1358 ".align 2" "\n" \ 1359 ".globl " SYMBOL_STRING(cti_##op) "\n" \ 1360 SYMBOL_STRING(cti_##op) ":" "\n" \ 1361 "sts pr, r11" "\n" \ 1362 "mov.l r11, @(0x38, r15)" "\n" \ 1363 "mov.l .L2"SYMBOL_STRING(JITStubThunked_##op)",r0" "\n" \ 1364 "mov.l @(r0,r12),r11" "\n" \ 1365 "jsr @r11" "\n" \ 1366 "nop" "\n" \ 1367 "mov.l @(0x38, r15), r11 " "\n" \ 1368 "lds r11, pr " "\n" \ 1369 "rts" "\n" \ 1370 "nop" "\n" \ 1371 ".align 2" "\n" \ 1372 ".L2"SYMBOL_STRING(JITStubThunked_##op)":.long " SYMBOL_STRING(JITStubThunked_##op)"@GOT \n" \ 1373 ); \ 1374 rtype JITStubThunked_##op(STUB_ARGS_DECLARATION) 1375#else 1376#define DEFINE_STUB_FUNCTION(rtype, op) rtype JIT_STUB cti_##op(STUB_ARGS_DECLARATION) 1377#endif 1378 1379DEFINE_STUB_FUNCTION(EncodedJSValue, op_create_this) 1380{ 1381 STUB_INIT_STACK_FRAME(stackFrame); 1382 CallFrame* callFrame = stackFrame.callFrame; 1383 size_t inlineCapacity = stackFrame.args[0].int32(); 1384 1385 JSFunction* constructor = jsCast<JSFunction*>(callFrame->callee()); 1386#if !ASSERT_DISABLED 1387 ConstructData constructData; 1388 ASSERT(constructor->methodTable()->getConstructData(constructor, constructData) == ConstructTypeJS); 1389#endif 1390 1391 Structure* structure = constructor->allocationProfile(callFrame, inlineCapacity)->structure(); 1392 JSValue result = constructEmptyObject(callFrame, structure); 1393 1394 return JSValue::encode(result); 1395} 1396 1397DEFINE_STUB_FUNCTION(EncodedJSValue, op_convert_this) 1398{ 1399 STUB_INIT_STACK_FRAME(stackFrame); 1400 1401 JSValue v1 = stackFrame.args[0].jsValue(); 1402 CallFrame* callFrame = stackFrame.callFrame; 1403 1404 ASSERT(v1.isPrimitive()); 1405 1406 JSObject* result = v1.toThisObject(callFrame); 1407 CHECK_FOR_EXCEPTION_AT_END(); 1408 return JSValue::encode(result); 1409} 1410 1411DEFINE_STUB_FUNCTION(EncodedJSValue, op_add) 1412{ 1413 STUB_INIT_STACK_FRAME(stackFrame); 1414 1415 JSValue v1 = stackFrame.args[0].jsValue(); 1416 JSValue v2 = stackFrame.args[1].jsValue(); 1417 CallFrame* callFrame = stackFrame.callFrame; 1418 1419 if (v1.isString() && !v2.isObject()) { 1420 JSValue result = jsString(callFrame, asString(v1), v2.toString(callFrame)); 1421 CHECK_FOR_EXCEPTION_AT_END(); 1422 return JSValue::encode(result); 1423 } 1424 1425 if (v1.isNumber() && v2.isNumber()) 1426 return JSValue::encode(jsNumber(v1.asNumber() + v2.asNumber())); 1427 1428 // All other cases are pretty uncommon 1429 JSValue result = jsAddSlowCase(callFrame, v1, v2); 1430 CHECK_FOR_EXCEPTION_AT_END(); 1431 return JSValue::encode(result); 1432} 1433 1434DEFINE_STUB_FUNCTION(EncodedJSValue, op_inc) 1435{ 1436 STUB_INIT_STACK_FRAME(stackFrame); 1437 1438 JSValue v = stackFrame.args[0].jsValue(); 1439 1440 CallFrame* callFrame = stackFrame.callFrame; 1441 JSValue result = jsNumber(v.toNumber(callFrame) + 1); 1442 CHECK_FOR_EXCEPTION_AT_END(); 1443 return JSValue::encode(result); 1444} 1445 1446DEFINE_STUB_FUNCTION(void, handle_watchdog_timer) 1447{ 1448 STUB_INIT_STACK_FRAME(stackFrame); 1449 CallFrame* callFrame = stackFrame.callFrame; 1450 VM* vm = stackFrame.vm; 1451 if (UNLIKELY(vm->watchdog.didFire(callFrame))) { 1452 vm->exception = createTerminatedExecutionException(vm); 1453 VM_THROW_EXCEPTION_AT_END(); 1454 return; 1455 } 1456} 1457 1458DEFINE_STUB_FUNCTION(void*, stack_check) 1459{ 1460 STUB_INIT_STACK_FRAME(stackFrame); 1461 CallFrame* callFrame = stackFrame.callFrame; 1462 1463 if (UNLIKELY(!stackFrame.stack->grow(&callFrame->registers()[callFrame->codeBlock()->m_numCalleeRegisters]))) 1464 return throwExceptionFromOpCall<void*>(stackFrame, callFrame, STUB_RETURN_ADDRESS, createStackOverflowError(callFrame->callerFrame())); 1465 1466 return callFrame; 1467} 1468 1469DEFINE_STUB_FUNCTION(JSObject*, op_new_object) 1470{ 1471 STUB_INIT_STACK_FRAME(stackFrame); 1472 1473 return constructEmptyObject(stackFrame.callFrame, stackFrame.args[0].structure()); 1474} 1475 1476DEFINE_STUB_FUNCTION(void, op_put_by_id_generic) 1477{ 1478 STUB_INIT_STACK_FRAME(stackFrame); 1479 1480 PutPropertySlot slot(stackFrame.callFrame->codeBlock()->isStrictMode()); 1481 stackFrame.args[0].jsValue().put(stackFrame.callFrame, stackFrame.args[1].identifier(), stackFrame.args[2].jsValue(), slot); 1482 CHECK_FOR_EXCEPTION_AT_END(); 1483} 1484 1485DEFINE_STUB_FUNCTION(void, op_put_by_id_direct_generic) 1486{ 1487 STUB_INIT_STACK_FRAME(stackFrame); 1488 1489 PutPropertySlot slot(stackFrame.callFrame->codeBlock()->isStrictMode()); 1490 JSValue baseValue = stackFrame.args[0].jsValue(); 1491 ASSERT(baseValue.isObject()); 1492 asObject(baseValue)->putDirect(stackFrame.callFrame->vm(), stackFrame.args[1].identifier(), stackFrame.args[2].jsValue(), slot); 1493 CHECK_FOR_EXCEPTION_AT_END(); 1494} 1495 1496DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_id_generic) 1497{ 1498 STUB_INIT_STACK_FRAME(stackFrame); 1499 1500 CallFrame* callFrame = stackFrame.callFrame; 1501 Identifier& ident = stackFrame.args[1].identifier(); 1502 1503 JSValue baseValue = stackFrame.args[0].jsValue(); 1504 PropertySlot slot(baseValue); 1505 JSValue result = baseValue.get(callFrame, ident, slot); 1506 1507 CHECK_FOR_EXCEPTION_AT_END(); 1508 return JSValue::encode(result); 1509} 1510 1511DEFINE_STUB_FUNCTION(void, op_put_by_id) 1512{ 1513 STUB_INIT_STACK_FRAME(stackFrame); 1514 CallFrame* callFrame = stackFrame.callFrame; 1515 Identifier& ident = stackFrame.args[1].identifier(); 1516 1517 CodeBlock* codeBlock = stackFrame.callFrame->codeBlock(); 1518 StructureStubInfo* stubInfo = &codeBlock->getStubInfo(STUB_RETURN_ADDRESS); 1519 AccessType accessType = static_cast<AccessType>(stubInfo->accessType); 1520 1521 PutPropertySlot slot(callFrame->codeBlock()->isStrictMode()); 1522 stackFrame.args[0].jsValue().put(callFrame, ident, stackFrame.args[2].jsValue(), slot); 1523 1524 if (accessType == static_cast<AccessType>(stubInfo->accessType)) { 1525 if (!stubInfo->seenOnce()) 1526 stubInfo->setSeen(); 1527 else 1528 tryCachePutByID(callFrame, codeBlock, STUB_RETURN_ADDRESS, stackFrame.args[0].jsValue(), slot, stubInfo, false); 1529 } 1530 1531 CHECK_FOR_EXCEPTION_AT_END(); 1532} 1533 1534DEFINE_STUB_FUNCTION(void, op_put_by_id_direct) 1535{ 1536 STUB_INIT_STACK_FRAME(stackFrame); 1537 CallFrame* callFrame = stackFrame.callFrame; 1538 Identifier& ident = stackFrame.args[1].identifier(); 1539 1540 CodeBlock* codeBlock = stackFrame.callFrame->codeBlock(); 1541 StructureStubInfo* stubInfo = &codeBlock->getStubInfo(STUB_RETURN_ADDRESS); 1542 AccessType accessType = static_cast<AccessType>(stubInfo->accessType); 1543 1544 PutPropertySlot slot(callFrame->codeBlock()->isStrictMode()); 1545 JSValue baseValue = stackFrame.args[0].jsValue(); 1546 ASSERT(baseValue.isObject()); 1547 1548 asObject(baseValue)->putDirect(callFrame->vm(), ident, stackFrame.args[2].jsValue(), slot); 1549 1550 if (accessType == static_cast<AccessType>(stubInfo->accessType)) { 1551 if (!stubInfo->seenOnce()) 1552 stubInfo->setSeen(); 1553 else 1554 tryCachePutByID(callFrame, codeBlock, STUB_RETURN_ADDRESS, stackFrame.args[0].jsValue(), slot, stubInfo, true); 1555 } 1556 1557 CHECK_FOR_EXCEPTION_AT_END(); 1558} 1559 1560DEFINE_STUB_FUNCTION(void, op_put_by_id_fail) 1561{ 1562 STUB_INIT_STACK_FRAME(stackFrame); 1563 1564 CallFrame* callFrame = stackFrame.callFrame; 1565 Identifier& ident = stackFrame.args[1].identifier(); 1566 1567 PutPropertySlot slot(callFrame->codeBlock()->isStrictMode()); 1568 stackFrame.args[0].jsValue().put(callFrame, ident, stackFrame.args[2].jsValue(), slot); 1569 1570 CHECK_FOR_EXCEPTION_AT_END(); 1571} 1572 1573DEFINE_STUB_FUNCTION(void, op_put_by_id_direct_fail) 1574{ 1575 STUB_INIT_STACK_FRAME(stackFrame); 1576 1577 CallFrame* callFrame = stackFrame.callFrame; 1578 Identifier& ident = stackFrame.args[1].identifier(); 1579 1580 PutPropertySlot slot(callFrame->codeBlock()->isStrictMode()); 1581 JSValue baseValue = stackFrame.args[0].jsValue(); 1582 ASSERT(baseValue.isObject()); 1583 asObject(baseValue)->putDirect(callFrame->vm(), ident, stackFrame.args[2].jsValue(), slot); 1584 1585 CHECK_FOR_EXCEPTION_AT_END(); 1586} 1587 1588DEFINE_STUB_FUNCTION(JSObject*, op_put_by_id_transition_realloc) 1589{ 1590 STUB_INIT_STACK_FRAME(stackFrame); 1591 1592 JSValue baseValue = stackFrame.args[0].jsValue(); 1593 int32_t oldSize = stackFrame.args[3].int32(); 1594 Structure* newStructure = stackFrame.args[4].structure(); 1595 int32_t newSize = newStructure->outOfLineCapacity(); 1596 1597 ASSERT(oldSize >= 0); 1598 ASSERT(newSize > oldSize); 1599 1600 ASSERT(baseValue.isObject()); 1601 JSObject* base = asObject(baseValue); 1602 VM& vm = *stackFrame.vm; 1603 Butterfly* butterfly = base->growOutOfLineStorage(vm, oldSize, newSize); 1604 base->setButterfly(vm, butterfly, newStructure); 1605 1606 return base; 1607} 1608 1609DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_id) 1610{ 1611 STUB_INIT_STACK_FRAME(stackFrame); 1612 CallFrame* callFrame = stackFrame.callFrame; 1613 Identifier& ident = stackFrame.args[1].identifier(); 1614 1615 CodeBlock* codeBlock = stackFrame.callFrame->codeBlock(); 1616 StructureStubInfo* stubInfo = &codeBlock->getStubInfo(STUB_RETURN_ADDRESS); 1617 AccessType accessType = static_cast<AccessType>(stubInfo->accessType); 1618 1619 JSValue baseValue = stackFrame.args[0].jsValue(); 1620 PropertySlot slot(baseValue); 1621 JSValue result = baseValue.get(callFrame, ident, slot); 1622 1623 if (accessType != static_cast<AccessType>(stubInfo->accessType)) 1624 return JSValue::encode(result); 1625 1626 if (!stubInfo->seenOnce()) 1627 stubInfo->setSeen(); 1628 else 1629 tryCacheGetByID(callFrame, codeBlock, STUB_RETURN_ADDRESS, baseValue, ident, slot, stubInfo); 1630 1631 CHECK_FOR_EXCEPTION_AT_END(); 1632 return JSValue::encode(result); 1633} 1634 1635DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_id_self_fail) 1636{ 1637 STUB_INIT_STACK_FRAME(stackFrame); 1638 1639 CallFrame* callFrame = stackFrame.callFrame; 1640 Identifier& ident = stackFrame.args[1].identifier(); 1641 1642 CodeBlock* codeBlock = callFrame->codeBlock(); 1643 StructureStubInfo* stubInfo = &codeBlock->getStubInfo(STUB_RETURN_ADDRESS); 1644 AccessType accessType = static_cast<AccessType>(stubInfo->accessType); 1645 1646 JSValue baseValue = stackFrame.args[0].jsValue(); 1647 PropertySlot slot(baseValue); 1648 JSValue result = baseValue.get(callFrame, ident, slot); 1649 1650 if (accessType != static_cast<AccessType>(stubInfo->accessType)) 1651 return JSValue::encode(result); 1652 1653 CHECK_FOR_EXCEPTION(); 1654 1655 if (baseValue.isCell() 1656 && slot.isCacheable() 1657 && !baseValue.asCell()->structure()->isUncacheableDictionary() 1658 && slot.slotBase() == baseValue) { 1659 1660 ASSERT(slot.slotBase().isObject()); 1661 1662 PolymorphicAccessStructureList* polymorphicStructureList; 1663 int listIndex = 1; 1664 1665 if (stubInfo->accessType == access_unset) 1666 stubInfo->initGetByIdSelf(callFrame->vm(), codeBlock->ownerExecutable(), baseValue.asCell()->structure()); 1667 1668 if (stubInfo->accessType == access_get_by_id_self) { 1669 ASSERT(!stubInfo->stubRoutine); 1670 polymorphicStructureList = new PolymorphicAccessStructureList(callFrame->vm(), codeBlock->ownerExecutable(), 0, stubInfo->u.getByIdSelf.baseObjectStructure.get(), true); 1671 stubInfo->initGetByIdSelfList(polymorphicStructureList, 1); 1672 } else { 1673 polymorphicStructureList = stubInfo->u.getByIdSelfList.structureList; 1674 listIndex = stubInfo->u.getByIdSelfList.listSize; 1675 } 1676 if (listIndex < POLYMORPHIC_LIST_CACHE_SIZE) { 1677 stubInfo->u.getByIdSelfList.listSize++; 1678 JIT::compileGetByIdSelfList(callFrame->scope()->vm(), codeBlock, stubInfo, polymorphicStructureList, listIndex, baseValue.asCell()->structure(), ident, slot, slot.cachedOffset()); 1679 1680 if (listIndex == (POLYMORPHIC_LIST_CACHE_SIZE - 1)) 1681 ctiPatchCallByReturnAddress(codeBlock, STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_id_generic)); 1682 } 1683 } else 1684 ctiPatchCallByReturnAddress(callFrame->codeBlock(), STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_id_generic)); 1685 return JSValue::encode(result); 1686} 1687 1688static PolymorphicAccessStructureList* getPolymorphicAccessStructureListSlot(VM& vm, ScriptExecutable* owner, StructureStubInfo* stubInfo, int& listIndex) 1689{ 1690 PolymorphicAccessStructureList* prototypeStructureList = 0; 1691 listIndex = 1; 1692 1693 switch (stubInfo->accessType) { 1694 case access_get_by_id_proto: 1695 prototypeStructureList = new PolymorphicAccessStructureList(vm, owner, stubInfo->stubRoutine, stubInfo->u.getByIdProto.baseObjectStructure.get(), stubInfo->u.getByIdProto.prototypeStructure.get(), true); 1696 stubInfo->stubRoutine.clear(); 1697 stubInfo->initGetByIdProtoList(prototypeStructureList, 2); 1698 break; 1699 case access_get_by_id_chain: 1700 prototypeStructureList = new PolymorphicAccessStructureList(vm, owner, stubInfo->stubRoutine, stubInfo->u.getByIdChain.baseObjectStructure.get(), stubInfo->u.getByIdChain.chain.get(), true); 1701 stubInfo->stubRoutine.clear(); 1702 stubInfo->initGetByIdProtoList(prototypeStructureList, 2); 1703 break; 1704 case access_get_by_id_proto_list: 1705 prototypeStructureList = stubInfo->u.getByIdProtoList.structureList; 1706 listIndex = stubInfo->u.getByIdProtoList.listSize; 1707 if (listIndex < POLYMORPHIC_LIST_CACHE_SIZE) 1708 stubInfo->u.getByIdProtoList.listSize++; 1709 break; 1710 default: 1711 RELEASE_ASSERT_NOT_REACHED(); 1712 } 1713 1714 ASSERT(listIndex <= POLYMORPHIC_LIST_CACHE_SIZE); 1715 return prototypeStructureList; 1716} 1717 1718DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_id_getter_stub) 1719{ 1720 STUB_INIT_STACK_FRAME(stackFrame); 1721 CallFrame* callFrame = stackFrame.callFrame; 1722 GetterSetter* getterSetter = asGetterSetter(stackFrame.args[0].jsObject()); 1723 if (!getterSetter->getter()) 1724 return JSValue::encode(jsUndefined()); 1725 JSObject* getter = asObject(getterSetter->getter()); 1726 CallData callData; 1727 CallType callType = getter->methodTable()->getCallData(getter, callData); 1728 JSValue result = call(callFrame, getter, callType, callData, stackFrame.args[1].jsObject(), ArgList()); 1729 if (callFrame->hadException()) 1730 returnToThrowTrampoline(&callFrame->vm(), stackFrame.args[2].returnAddress(), STUB_RETURN_ADDRESS); 1731 1732 return JSValue::encode(result); 1733} 1734 1735DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_id_custom_stub) 1736{ 1737 STUB_INIT_STACK_FRAME(stackFrame); 1738 CallFrame* callFrame = stackFrame.callFrame; 1739 JSObject* slotBase = stackFrame.args[0].jsObject(); 1740 PropertySlot::GetValueFunc getter = reinterpret_cast<PropertySlot::GetValueFunc>(stackFrame.args[1].asPointer); 1741 const Identifier& ident = stackFrame.args[2].identifier(); 1742 JSValue result = getter(callFrame, slotBase, ident); 1743 if (callFrame->hadException()) 1744 returnToThrowTrampoline(&callFrame->vm(), stackFrame.args[3].returnAddress(), STUB_RETURN_ADDRESS); 1745 1746 return JSValue::encode(result); 1747} 1748 1749DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_id_proto_list) 1750{ 1751 STUB_INIT_STACK_FRAME(stackFrame); 1752 1753 CallFrame* callFrame = stackFrame.callFrame; 1754 const Identifier& propertyName = stackFrame.args[1].identifier(); 1755 1756 CodeBlock* codeBlock = callFrame->codeBlock(); 1757 StructureStubInfo* stubInfo = &codeBlock->getStubInfo(STUB_RETURN_ADDRESS); 1758 AccessType accessType = static_cast<AccessType>(stubInfo->accessType); 1759 1760 JSValue baseValue = stackFrame.args[0].jsValue(); 1761 PropertySlot slot(baseValue); 1762 JSValue result = baseValue.get(callFrame, propertyName, slot); 1763 1764 CHECK_FOR_EXCEPTION(); 1765 1766 if (accessType != static_cast<AccessType>(stubInfo->accessType) 1767 || !baseValue.isCell() 1768 || !slot.isCacheable() 1769 || baseValue.asCell()->structure()->isDictionary() 1770 || baseValue.asCell()->structure()->typeInfo().prohibitsPropertyCaching()) { 1771 ctiPatchCallByReturnAddress(callFrame->codeBlock(), STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_id_proto_fail)); 1772 return JSValue::encode(result); 1773 } 1774 1775 Structure* structure = baseValue.asCell()->structure(); 1776 1777 ASSERT(slot.slotBase().isObject()); 1778 JSObject* slotBaseObject = asObject(slot.slotBase()); 1779 1780 PropertyOffset offset = slot.cachedOffset(); 1781 1782 if (slot.slotBase() == baseValue) 1783 ctiPatchCallByReturnAddress(codeBlock, STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_id_proto_fail)); 1784 else if (slot.slotBase() == baseValue.asCell()->structure()->prototypeForLookup(callFrame)) { 1785 ASSERT(!baseValue.asCell()->structure()->isDictionary()); 1786 1787 if (baseValue.asCell()->structure()->typeInfo().hasImpureGetOwnPropertySlot()) { 1788 ctiPatchCallByReturnAddress(codeBlock, STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_id_proto_fail)); 1789 return JSValue::encode(result); 1790 } 1791 1792 // Since we're accessing a prototype in a loop, it's a good bet that it 1793 // should not be treated as a dictionary. 1794 if (slotBaseObject->structure()->isDictionary()) { 1795 slotBaseObject->flattenDictionaryObject(callFrame->vm()); 1796 offset = slotBaseObject->structure()->get(callFrame->vm(), propertyName); 1797 } 1798 1799 int listIndex; 1800 PolymorphicAccessStructureList* prototypeStructureList = getPolymorphicAccessStructureListSlot(callFrame->vm(), codeBlock->ownerExecutable(), stubInfo, listIndex); 1801 if (listIndex < POLYMORPHIC_LIST_CACHE_SIZE) { 1802 JIT::compileGetByIdProtoList(callFrame->scope()->vm(), callFrame, codeBlock, stubInfo, prototypeStructureList, listIndex, structure, slotBaseObject->structure(), propertyName, slot, offset); 1803 1804 if (listIndex == (POLYMORPHIC_LIST_CACHE_SIZE - 1)) 1805 ctiPatchCallByReturnAddress(codeBlock, STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_id_proto_list_full)); 1806 } 1807 } else { 1808 size_t count = normalizePrototypeChainForChainAccess(callFrame, baseValue, slot.slotBase(), propertyName, offset); 1809 if (count == InvalidPrototypeChain) { 1810 ctiPatchCallByReturnAddress(codeBlock, STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_id_proto_fail)); 1811 return JSValue::encode(result); 1812 } 1813 1814 ASSERT(!baseValue.asCell()->structure()->isDictionary()); 1815 int listIndex; 1816 PolymorphicAccessStructureList* prototypeStructureList = getPolymorphicAccessStructureListSlot(callFrame->vm(), codeBlock->ownerExecutable(), stubInfo, listIndex); 1817 1818 if (listIndex < POLYMORPHIC_LIST_CACHE_SIZE) { 1819 StructureChain* protoChain = structure->prototypeChain(callFrame); 1820 JIT::compileGetByIdChainList(callFrame->scope()->vm(), callFrame, codeBlock, stubInfo, prototypeStructureList, listIndex, structure, protoChain, count, propertyName, slot, offset); 1821 1822 if (listIndex == (POLYMORPHIC_LIST_CACHE_SIZE - 1)) 1823 ctiPatchCallByReturnAddress(codeBlock, STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_id_proto_list_full)); 1824 } 1825 } 1826 1827 return JSValue::encode(result); 1828} 1829 1830DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_id_proto_list_full) 1831{ 1832 STUB_INIT_STACK_FRAME(stackFrame); 1833 1834 JSValue baseValue = stackFrame.args[0].jsValue(); 1835 PropertySlot slot(baseValue); 1836 JSValue result = baseValue.get(stackFrame.callFrame, stackFrame.args[1].identifier(), slot); 1837 1838 CHECK_FOR_EXCEPTION_AT_END(); 1839 return JSValue::encode(result); 1840} 1841 1842DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_id_proto_fail) 1843{ 1844 STUB_INIT_STACK_FRAME(stackFrame); 1845 1846 JSValue baseValue = stackFrame.args[0].jsValue(); 1847 PropertySlot slot(baseValue); 1848 JSValue result = baseValue.get(stackFrame.callFrame, stackFrame.args[1].identifier(), slot); 1849 1850 CHECK_FOR_EXCEPTION_AT_END(); 1851 return JSValue::encode(result); 1852} 1853 1854DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_id_array_fail) 1855{ 1856 STUB_INIT_STACK_FRAME(stackFrame); 1857 1858 JSValue baseValue = stackFrame.args[0].jsValue(); 1859 PropertySlot slot(baseValue); 1860 JSValue result = baseValue.get(stackFrame.callFrame, stackFrame.args[1].identifier(), slot); 1861 1862 CHECK_FOR_EXCEPTION_AT_END(); 1863 return JSValue::encode(result); 1864} 1865 1866DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_id_string_fail) 1867{ 1868 STUB_INIT_STACK_FRAME(stackFrame); 1869 1870 JSValue baseValue = stackFrame.args[0].jsValue(); 1871 PropertySlot slot(baseValue); 1872 JSValue result = baseValue.get(stackFrame.callFrame, stackFrame.args[1].identifier(), slot); 1873 1874 CHECK_FOR_EXCEPTION_AT_END(); 1875 return JSValue::encode(result); 1876} 1877 1878DEFINE_STUB_FUNCTION(EncodedJSValue, op_check_has_instance) 1879{ 1880 STUB_INIT_STACK_FRAME(stackFrame); 1881 1882 CallFrame* callFrame = stackFrame.callFrame; 1883 JSValue value = stackFrame.args[0].jsValue(); 1884 JSValue baseVal = stackFrame.args[1].jsValue(); 1885 1886 if (baseVal.isObject()) { 1887 JSObject* baseObject = asObject(baseVal); 1888 ASSERT(!baseObject->structure()->typeInfo().implementsDefaultHasInstance()); 1889 if (baseObject->structure()->typeInfo().implementsHasInstance()) { 1890 bool result = baseObject->methodTable()->customHasInstance(baseObject, callFrame, value); 1891 CHECK_FOR_EXCEPTION_AT_END(); 1892 return JSValue::encode(jsBoolean(result)); 1893 } 1894 } 1895 1896 stackFrame.vm->exception = createInvalidParamError(callFrame, "instanceof", baseVal); 1897 VM_THROW_EXCEPTION_AT_END(); 1898 return JSValue::encode(JSValue()); 1899} 1900 1901#if ENABLE(DFG_JIT) 1902DEFINE_STUB_FUNCTION(void, optimize) 1903{ 1904 STUB_INIT_STACK_FRAME(stackFrame); 1905 1906 CallFrame* callFrame = stackFrame.callFrame; 1907 CodeBlock* codeBlock = callFrame->codeBlock(); 1908 unsigned bytecodeIndex = stackFrame.args[0].int32(); 1909 1910#if ENABLE(JIT_VERBOSE_OSR) 1911 dataLog( 1912 *codeBlock, ": Entered optimize with bytecodeIndex = ", bytecodeIndex, 1913 ", executeCounter = ", codeBlock->jitExecuteCounter(), 1914 ", optimizationDelayCounter = ", codeBlock->reoptimizationRetryCounter(), 1915 ", exitCounter = "); 1916 if (codeBlock->hasOptimizedReplacement()) 1917 dataLog(codeBlock->replacement()->osrExitCounter()); 1918 else 1919 dataLog("N/A"); 1920 dataLog("\n"); 1921#endif 1922 1923 if (!codeBlock->checkIfOptimizationThresholdReached()) { 1924 codeBlock->updateAllPredictions(); 1925#if ENABLE(JIT_VERBOSE_OSR) 1926 dataLog("Choosing not to optimize ", *codeBlock, " yet.\n"); 1927#endif 1928 return; 1929 } 1930 1931 if (codeBlock->hasOptimizedReplacement()) { 1932#if ENABLE(JIT_VERBOSE_OSR) 1933 dataLog("Considering OSR ", *codeBlock, " -> ", *codeBlock->replacement(), ".\n"); 1934#endif 1935 // If we have an optimized replacement, then it must be the case that we entered 1936 // cti_optimize from a loop. That's because is there's an optimized replacement, 1937 // then all calls to this function will be relinked to the replacement and so 1938 // the prologue OSR will never fire. 1939 1940 // This is an interesting threshold check. Consider that a function OSR exits 1941 // in the middle of a loop, while having a relatively low exit count. The exit 1942 // will reset the execution counter to some target threshold, meaning that this 1943 // code won't be reached until that loop heats up for >=1000 executions. But then 1944 // we do a second check here, to see if we should either reoptimize, or just 1945 // attempt OSR entry. Hence it might even be correct for 1946 // shouldReoptimizeFromLoopNow() to always return true. But we make it do some 1947 // additional checking anyway, to reduce the amount of recompilation thrashing. 1948 if (codeBlock->replacement()->shouldReoptimizeFromLoopNow()) { 1949#if ENABLE(JIT_VERBOSE_OSR) 1950 dataLog("Triggering reoptimization of ", *codeBlock, "(", *codeBlock->replacement(), ") (in loop).\n"); 1951#endif 1952 codeBlock->reoptimize(); 1953 return; 1954 } 1955 } else { 1956 if (!codeBlock->shouldOptimizeNow()) { 1957#if ENABLE(JIT_VERBOSE_OSR) 1958 dataLog("Delaying optimization for ", *codeBlock, " (in loop) because of insufficient profiling.\n"); 1959#endif 1960 return; 1961 } 1962 1963#if ENABLE(JIT_VERBOSE_OSR) 1964 dataLog("Triggering optimized compilation of ", *codeBlock, "\n"); 1965#endif 1966 1967 JSScope* scope = callFrame->scope(); 1968 JSObject* error = codeBlock->compileOptimized(callFrame, scope, bytecodeIndex); 1969#if ENABLE(JIT_VERBOSE_OSR) 1970 if (error) 1971 dataLog("WARNING: optimized compilation failed.\n"); 1972#else 1973 UNUSED_PARAM(error); 1974#endif 1975 1976 if (codeBlock->replacement() == codeBlock) { 1977#if ENABLE(JIT_VERBOSE_OSR) 1978 dataLog("Optimizing ", *codeBlock, " failed.\n"); 1979#endif 1980 1981 ASSERT(codeBlock->getJITType() == JITCode::BaselineJIT); 1982 codeBlock->dontOptimizeAnytimeSoon(); 1983 return; 1984 } 1985 } 1986 1987 CodeBlock* optimizedCodeBlock = codeBlock->replacement(); 1988 ASSERT(optimizedCodeBlock->getJITType() == JITCode::DFGJIT); 1989 1990 if (void* address = DFG::prepareOSREntry(callFrame, optimizedCodeBlock, bytecodeIndex)) { 1991 if (Options::showDFGDisassembly()) { 1992 dataLog( 1993 "Performing OSR ", *codeBlock, " -> ", *optimizedCodeBlock, ", address ", 1994 RawPointer((STUB_RETURN_ADDRESS).value()), " -> ", RawPointer(address), ".\n"); 1995 } 1996#if ENABLE(JIT_VERBOSE_OSR) 1997 dataLog("Optimizing ", *codeBlock, " succeeded, performing OSR after a delay of ", codeBlock->optimizationDelayCounter(), ".\n"); 1998#endif 1999 2000 codeBlock->optimizeSoon(); 2001 STUB_SET_RETURN_ADDRESS(address); 2002 return; 2003 } 2004 2005#if ENABLE(JIT_VERBOSE_OSR) 2006 dataLog("Optimizing ", *codeBlock, " succeeded, OSR failed, after a delay of ", codeBlock->optimizationDelayCounter(), ".\n"); 2007#endif 2008 2009 // Count the OSR failure as a speculation failure. If this happens a lot, then 2010 // reoptimize. 2011 optimizedCodeBlock->countOSRExit(); 2012 2013#if ENABLE(JIT_VERBOSE_OSR) 2014 dataLog("Encountered OSR failure ", *codeBlock, " -> ", *codeBlock->replacement(), ".\n"); 2015#endif 2016 2017 // We are a lot more conservative about triggering reoptimization after OSR failure than 2018 // before it. If we enter the optimize_from_loop trigger with a bucket full of fail 2019 // already, then we really would like to reoptimize immediately. But this case covers 2020 // something else: there weren't many (or any) speculation failures before, but we just 2021 // failed to enter the speculative code because some variable had the wrong value or 2022 // because the OSR code decided for any spurious reason that it did not want to OSR 2023 // right now. So, we only trigger reoptimization only upon the more conservative (non-loop) 2024 // reoptimization trigger. 2025 if (optimizedCodeBlock->shouldReoptimizeNow()) { 2026#if ENABLE(JIT_VERBOSE_OSR) 2027 dataLog("Triggering reoptimization of ", *codeBlock, " -> ", *codeBlock->replacement(), " (after OSR fail).\n"); 2028#endif 2029 codeBlock->reoptimize(); 2030 return; 2031 } 2032 2033 // OSR failed this time, but it might succeed next time! Let the code run a bit 2034 // longer and then try again. 2035 codeBlock->optimizeAfterWarmUp(); 2036} 2037#endif // ENABLE(DFG_JIT) 2038 2039DEFINE_STUB_FUNCTION(EncodedJSValue, op_instanceof) 2040{ 2041 STUB_INIT_STACK_FRAME(stackFrame); 2042 2043 CallFrame* callFrame = stackFrame.callFrame; 2044 JSValue value = stackFrame.args[0].jsValue(); 2045 JSValue proto = stackFrame.args[1].jsValue(); 2046 2047 ASSERT(!value.isObject() || !proto.isObject()); 2048 2049 bool result = JSObject::defaultHasInstance(callFrame, value, proto); 2050 CHECK_FOR_EXCEPTION_AT_END(); 2051 return JSValue::encode(jsBoolean(result)); 2052} 2053 2054DEFINE_STUB_FUNCTION(EncodedJSValue, op_del_by_id) 2055{ 2056 STUB_INIT_STACK_FRAME(stackFrame); 2057 2058 CallFrame* callFrame = stackFrame.callFrame; 2059 2060 JSObject* baseObj = stackFrame.args[0].jsValue().toObject(callFrame); 2061 2062 bool couldDelete = baseObj->methodTable()->deleteProperty(baseObj, callFrame, stackFrame.args[1].identifier()); 2063 JSValue result = jsBoolean(couldDelete); 2064 if (!couldDelete && callFrame->codeBlock()->isStrictMode()) 2065 stackFrame.vm->exception = createTypeError(stackFrame.callFrame, "Unable to delete property."); 2066 2067 CHECK_FOR_EXCEPTION_AT_END(); 2068 return JSValue::encode(result); 2069} 2070 2071DEFINE_STUB_FUNCTION(EncodedJSValue, op_mul) 2072{ 2073 STUB_INIT_STACK_FRAME(stackFrame); 2074 2075 JSValue src1 = stackFrame.args[0].jsValue(); 2076 JSValue src2 = stackFrame.args[1].jsValue(); 2077 2078 if (src1.isNumber() && src2.isNumber()) 2079 return JSValue::encode(jsNumber(src1.asNumber() * src2.asNumber())); 2080 2081 CallFrame* callFrame = stackFrame.callFrame; 2082 JSValue result = jsNumber(src1.toNumber(callFrame) * src2.toNumber(callFrame)); 2083 CHECK_FOR_EXCEPTION_AT_END(); 2084 return JSValue::encode(result); 2085} 2086 2087DEFINE_STUB_FUNCTION(JSObject*, op_new_func) 2088{ 2089 STUB_INIT_STACK_FRAME(stackFrame); 2090 2091 ASSERT(stackFrame.callFrame->codeBlock()->codeType() != FunctionCode || !stackFrame.callFrame->codeBlock()->needsFullScopeChain() || stackFrame.callFrame->uncheckedR(stackFrame.callFrame->codeBlock()->activationRegister()).jsValue()); 2092 return JSFunction::create(stackFrame.callFrame, stackFrame.args[0].function(), stackFrame.callFrame->scope()); 2093} 2094 2095inline void* jitCompileFor(CallFrame* callFrame, CodeSpecializationKind kind) 2096{ 2097 // This function is called by cti_op_call_jitCompile() and 2098 // cti_op_construct_jitCompile() JIT glue trampolines to compile the 2099 // callee function that we want to call. Both cti glue trampolines are 2100 // called by JIT'ed code which has pushed a frame and initialized most of 2101 // the frame content except for the codeBlock. 2102 // 2103 // Normally, the prologue of the callee is supposed to set the frame's cb 2104 // pointer to the cb of the callee. But in this case, the callee code does 2105 // not exist yet until it is compiled below. The compilation process will 2106 // allocate memory which may trigger a GC. The GC, in turn, will scan the 2107 // JSStack, and will expect the frame's cb to either be valid or 0. If 2108 // we don't initialize it, the GC will be accessing invalid memory and may 2109 // crash. 2110 // 2111 // Hence, we should nullify it here before proceeding with the compilation. 2112 callFrame->setCodeBlock(0); 2113 2114 JSFunction* function = jsCast<JSFunction*>(callFrame->callee()); 2115 ASSERT(!function->isHostFunction()); 2116 FunctionExecutable* executable = function->jsExecutable(); 2117 JSScope* callDataScopeChain = function->scope(); 2118 JSObject* error = executable->compileFor(callFrame, callDataScopeChain, kind); 2119 if (!error) 2120 return function; 2121 callFrame->vm().exception = error; 2122 return 0; 2123} 2124 2125DEFINE_STUB_FUNCTION(void*, op_call_jitCompile) 2126{ 2127 STUB_INIT_STACK_FRAME(stackFrame); 2128 2129#if !ASSERT_DISABLED 2130 CallData callData; 2131 ASSERT(stackFrame.callFrame->callee()->methodTable()->getCallData(stackFrame.callFrame->callee(), callData) == CallTypeJS); 2132#endif 2133 2134 CallFrame* callFrame = stackFrame.callFrame; 2135 void* result = jitCompileFor(callFrame, CodeForCall); 2136 if (!result) 2137 return throwExceptionFromOpCall<void*>(stackFrame, callFrame, STUB_RETURN_ADDRESS); 2138 2139 return result; 2140} 2141 2142DEFINE_STUB_FUNCTION(void*, op_construct_jitCompile) 2143{ 2144 STUB_INIT_STACK_FRAME(stackFrame); 2145 2146#if !ASSERT_DISABLED 2147 ConstructData constructData; 2148 ASSERT(jsCast<JSFunction*>(stackFrame.callFrame->callee())->methodTable()->getConstructData(stackFrame.callFrame->callee(), constructData) == ConstructTypeJS); 2149#endif 2150 2151 CallFrame* callFrame = stackFrame.callFrame; 2152 void* result = jitCompileFor(callFrame, CodeForConstruct); 2153 if (!result) 2154 return throwExceptionFromOpCall<void*>(stackFrame, callFrame, STUB_RETURN_ADDRESS); 2155 2156 return result; 2157} 2158 2159DEFINE_STUB_FUNCTION(void*, op_call_arityCheck) 2160{ 2161 STUB_INIT_STACK_FRAME(stackFrame); 2162 2163 CallFrame* callFrame = stackFrame.callFrame; 2164 2165 CallFrame* newCallFrame = CommonSlowPaths::arityCheckFor(callFrame, stackFrame.stack, CodeForCall); 2166 if (!newCallFrame) 2167 return throwExceptionFromOpCall<void*>(stackFrame, callFrame, STUB_RETURN_ADDRESS, createStackOverflowError(callFrame->callerFrame())); 2168 2169 return newCallFrame; 2170} 2171 2172DEFINE_STUB_FUNCTION(void*, op_construct_arityCheck) 2173{ 2174 STUB_INIT_STACK_FRAME(stackFrame); 2175 2176 CallFrame* callFrame = stackFrame.callFrame; 2177 2178 CallFrame* newCallFrame = CommonSlowPaths::arityCheckFor(callFrame, stackFrame.stack, CodeForConstruct); 2179 if (!newCallFrame) 2180 return throwExceptionFromOpCall<void*>(stackFrame, callFrame, STUB_RETURN_ADDRESS, createStackOverflowError(callFrame->callerFrame())); 2181 2182 return newCallFrame; 2183} 2184 2185inline void* lazyLinkFor(CallFrame* callFrame, CodeSpecializationKind kind) 2186{ 2187 JSFunction* callee = jsCast<JSFunction*>(callFrame->callee()); 2188 ExecutableBase* executable = callee->executable(); 2189 2190 MacroAssemblerCodePtr codePtr; 2191 CodeBlock* codeBlock = 0; 2192 CallLinkInfo* callLinkInfo = &callFrame->callerFrame()->codeBlock()->getCallLinkInfo(callFrame->returnPC()); 2193 2194 // This function is called by cti_vm_lazyLinkCall() and 2195 // cti_lazyLinkConstruct JIT glue trampolines to link the callee function 2196 // that we want to call. Both cti glue trampolines are called by JIT'ed 2197 // code which has pushed a frame and initialized most of the frame content 2198 // except for the codeBlock. 2199 // 2200 // Normally, the prologue of the callee is supposed to set the frame's cb 2201 // field to the cb of the callee. But in this case, the callee may not 2202 // exist yet, and if not, it will be generated in the compilation below. 2203 // The compilation will allocate memory which may trigger a GC. The GC, in 2204 // turn, will scan the JSStack, and will expect the frame's cb to be valid 2205 // or 0. If we don't initialize it, the GC will be accessing invalid 2206 // memory and may crash. 2207 // 2208 // Hence, we should nullify it here before proceeding with the compilation. 2209 callFrame->setCodeBlock(0); 2210 2211 if (executable->isHostFunction()) 2212 codePtr = executable->generatedJITCodeFor(kind).addressForCall(); 2213 else { 2214 FunctionExecutable* functionExecutable = static_cast<FunctionExecutable*>(executable); 2215 if (JSObject* error = functionExecutable->compileFor(callFrame, callee->scope(), kind)) { 2216 callFrame->vm().exception = error; 2217 return 0; 2218 } 2219 codeBlock = &functionExecutable->generatedBytecodeFor(kind); 2220 if (callFrame->argumentCountIncludingThis() < static_cast<size_t>(codeBlock->numParameters()) 2221 || callLinkInfo->callType == CallLinkInfo::CallVarargs) 2222 codePtr = functionExecutable->generatedJITCodeWithArityCheckFor(kind); 2223 else 2224 codePtr = functionExecutable->generatedJITCodeFor(kind).addressForCall(); 2225 } 2226 2227 if (!callLinkInfo->seenOnce()) 2228 callLinkInfo->setSeen(); 2229 else 2230 JIT::linkFor(callee, callFrame->callerFrame()->codeBlock(), codeBlock, codePtr, callLinkInfo, &callFrame->vm(), kind); 2231 2232 return codePtr.executableAddress(); 2233} 2234 2235DEFINE_STUB_FUNCTION(void*, vm_lazyLinkCall) 2236{ 2237 STUB_INIT_STACK_FRAME(stackFrame); 2238 2239 CallFrame* callFrame = stackFrame.callFrame; 2240 void* result = lazyLinkFor(callFrame, CodeForCall); 2241 if (!result) 2242 return throwExceptionFromOpCall<void*>(stackFrame, callFrame, STUB_RETURN_ADDRESS); 2243 2244 return result; 2245} 2246 2247DEFINE_STUB_FUNCTION(void*, vm_lazyLinkClosureCall) 2248{ 2249 STUB_INIT_STACK_FRAME(stackFrame); 2250 2251 CallFrame* callFrame = stackFrame.callFrame; 2252 2253 CodeBlock* callerCodeBlock = callFrame->callerFrame()->codeBlock(); 2254 VM* vm = callerCodeBlock->vm(); 2255 CallLinkInfo* callLinkInfo = &callerCodeBlock->getCallLinkInfo(callFrame->returnPC()); 2256 JSFunction* callee = jsCast<JSFunction*>(callFrame->callee()); 2257 ExecutableBase* executable = callee->executable(); 2258 Structure* structure = callee->structure(); 2259 2260 ASSERT(callLinkInfo->callType == CallLinkInfo::Call); 2261 ASSERT(callLinkInfo->isLinked()); 2262 ASSERT(callLinkInfo->callee); 2263 ASSERT(callee != callLinkInfo->callee.get()); 2264 2265 bool shouldLink = false; 2266 CodeBlock* calleeCodeBlock = 0; 2267 MacroAssemblerCodePtr codePtr; 2268 2269 if (executable == callLinkInfo->callee.get()->executable() 2270 && structure == callLinkInfo->callee.get()->structure()) { 2271 2272 shouldLink = true; 2273 2274 ASSERT(executable->hasJITCodeForCall()); 2275 codePtr = executable->generatedJITCodeForCall().addressForCall(); 2276 if (!callee->executable()->isHostFunction()) { 2277 calleeCodeBlock = &jsCast<FunctionExecutable*>(executable)->generatedBytecodeForCall(); 2278 if (callFrame->argumentCountIncludingThis() < static_cast<size_t>(calleeCodeBlock->numParameters())) { 2279 shouldLink = false; 2280 codePtr = executable->generatedJITCodeWithArityCheckFor(CodeForCall); 2281 } 2282 } 2283 } else if (callee->isHostFunction()) 2284 codePtr = executable->generatedJITCodeForCall().addressForCall(); 2285 else { 2286 // Need to clear the code block before compilation, because compilation can GC. 2287 callFrame->setCodeBlock(0); 2288 2289 FunctionExecutable* functionExecutable = jsCast<FunctionExecutable*>(executable); 2290 JSScope* scopeChain = callee->scope(); 2291 JSObject* error = functionExecutable->compileFor(callFrame, scopeChain, CodeForCall); 2292 if (error) { 2293 callFrame->vm().exception = error; 2294 return 0; 2295 } 2296 2297 codePtr = functionExecutable->generatedJITCodeWithArityCheckFor(CodeForCall); 2298 } 2299 2300 if (shouldLink) { 2301 ASSERT(codePtr); 2302 JIT::compileClosureCall(vm, callLinkInfo, callerCodeBlock, calleeCodeBlock, structure, executable, codePtr); 2303 callLinkInfo->hasSeenClosure = true; 2304 } else 2305 JIT::linkSlowCall(callerCodeBlock, callLinkInfo); 2306 2307 return codePtr.executableAddress(); 2308} 2309 2310DEFINE_STUB_FUNCTION(void*, vm_lazyLinkConstruct) 2311{ 2312 STUB_INIT_STACK_FRAME(stackFrame); 2313 2314 CallFrame* callFrame = stackFrame.callFrame; 2315 void* result = lazyLinkFor(callFrame, CodeForConstruct); 2316 if (!result) 2317 return throwExceptionFromOpCall<void*>(stackFrame, callFrame, STUB_RETURN_ADDRESS); 2318 2319 return result; 2320} 2321 2322DEFINE_STUB_FUNCTION(JSObject*, op_push_activation) 2323{ 2324 STUB_INIT_STACK_FRAME(stackFrame); 2325 2326 JSActivation* activation = JSActivation::create(stackFrame.callFrame->vm(), stackFrame.callFrame, stackFrame.callFrame->codeBlock()); 2327 stackFrame.callFrame->setScope(activation); 2328 return activation; 2329} 2330 2331DEFINE_STUB_FUNCTION(EncodedJSValue, op_call_NotJSFunction) 2332{ 2333 STUB_INIT_STACK_FRAME(stackFrame); 2334 2335 CallFrame* callFrame = stackFrame.callFrame; 2336 2337 JSValue callee = callFrame->calleeAsValue(); 2338 2339 CallData callData; 2340 CallType callType = getCallData(callee, callData); 2341 2342 ASSERT(callType != CallTypeJS); 2343 if (callType != CallTypeHost) { 2344 ASSERT(callType == CallTypeNone); 2345 return throwExceptionFromOpCall<EncodedJSValue>(stackFrame, callFrame, STUB_RETURN_ADDRESS, createNotAFunctionError(callFrame->callerFrame(), callee)); 2346 } 2347 2348 EncodedJSValue returnValue; 2349 { 2350 SamplingTool::CallRecord callRecord(CTI_SAMPLER, true); 2351 returnValue = callData.native.function(callFrame); 2352 } 2353 2354 if (stackFrame.vm->exception) 2355 return throwExceptionFromOpCall<EncodedJSValue>(stackFrame, callFrame, STUB_RETURN_ADDRESS); 2356 2357 return returnValue; 2358} 2359 2360DEFINE_STUB_FUNCTION(EncodedJSValue, op_create_arguments) 2361{ 2362 STUB_INIT_STACK_FRAME(stackFrame); 2363 2364 Arguments* arguments = Arguments::create(*stackFrame.vm, stackFrame.callFrame); 2365 return JSValue::encode(JSValue(arguments)); 2366} 2367 2368DEFINE_STUB_FUNCTION(void, op_tear_off_activation) 2369{ 2370 STUB_INIT_STACK_FRAME(stackFrame); 2371 2372 ASSERT(stackFrame.callFrame->codeBlock()->needsFullScopeChain()); 2373 jsCast<JSActivation*>(stackFrame.args[0].jsValue())->tearOff(*stackFrame.vm); 2374} 2375 2376DEFINE_STUB_FUNCTION(void, op_tear_off_arguments) 2377{ 2378 STUB_INIT_STACK_FRAME(stackFrame); 2379 2380 CallFrame* callFrame = stackFrame.callFrame; 2381 ASSERT(callFrame->codeBlock()->usesArguments()); 2382 Arguments* arguments = jsCast<Arguments*>(stackFrame.args[0].jsValue()); 2383 if (JSValue activationValue = stackFrame.args[1].jsValue()) { 2384 arguments->didTearOffActivation(callFrame, jsCast<JSActivation*>(activationValue)); 2385 return; 2386 } 2387 arguments->tearOff(callFrame); 2388} 2389 2390DEFINE_STUB_FUNCTION(void, op_profile_will_call) 2391{ 2392 STUB_INIT_STACK_FRAME(stackFrame); 2393 2394 if (LegacyProfiler* profiler = stackFrame.vm->enabledProfiler()) 2395 profiler->willExecute(stackFrame.callFrame, stackFrame.args[0].jsValue()); 2396} 2397 2398DEFINE_STUB_FUNCTION(void, op_profile_did_call) 2399{ 2400 STUB_INIT_STACK_FRAME(stackFrame); 2401 2402 if (LegacyProfiler* profiler = stackFrame.vm->enabledProfiler()) 2403 profiler->didExecute(stackFrame.callFrame, stackFrame.args[0].jsValue()); 2404} 2405 2406DEFINE_STUB_FUNCTION(JSObject*, op_new_array) 2407{ 2408 STUB_INIT_STACK_FRAME(stackFrame); 2409 2410 return constructArray(stackFrame.callFrame, stackFrame.args[2].arrayAllocationProfile(), reinterpret_cast<JSValue*>(&stackFrame.callFrame->registers()[stackFrame.args[0].int32()]), stackFrame.args[1].int32()); 2411} 2412 2413DEFINE_STUB_FUNCTION(JSObject*, op_new_array_with_size) 2414{ 2415 STUB_INIT_STACK_FRAME(stackFrame); 2416 2417 return constructArrayWithSizeQuirk(stackFrame.callFrame, stackFrame.args[1].arrayAllocationProfile(), stackFrame.callFrame->lexicalGlobalObject(), stackFrame.args[0].jsValue()); 2418} 2419 2420DEFINE_STUB_FUNCTION(JSObject*, op_new_array_buffer) 2421{ 2422 STUB_INIT_STACK_FRAME(stackFrame); 2423 2424 return constructArray(stackFrame.callFrame, stackFrame.args[2].arrayAllocationProfile(), stackFrame.callFrame->codeBlock()->constantBuffer(stackFrame.args[0].int32()), stackFrame.args[1].int32()); 2425} 2426 2427DEFINE_STUB_FUNCTION(void, op_init_global_const_check) 2428{ 2429 STUB_INIT_STACK_FRAME(stackFrame); 2430 2431 CallFrame* callFrame = stackFrame.callFrame; 2432 CodeBlock* codeBlock = callFrame->codeBlock(); 2433 symbolTablePut(codeBlock->globalObject(), callFrame, codeBlock->identifier(stackFrame.args[1].int32()), stackFrame.args[0].jsValue(), true); 2434} 2435 2436DEFINE_STUB_FUNCTION(EncodedJSValue, op_resolve) 2437{ 2438 STUB_INIT_STACK_FRAME(stackFrame); 2439 2440 CallFrame* callFrame = stackFrame.callFrame; 2441 2442 JSValue result = JSScope::resolve(callFrame, stackFrame.args[0].identifier(), stackFrame.args[1].resolveOperations()); 2443 CHECK_FOR_EXCEPTION_AT_END(); 2444 return JSValue::encode(result); 2445} 2446 2447DEFINE_STUB_FUNCTION(void, op_put_to_base) 2448{ 2449 STUB_INIT_STACK_FRAME(stackFrame); 2450 2451 CallFrame* callFrame = stackFrame.callFrame; 2452 JSValue base = callFrame->r(stackFrame.args[0].int32()).jsValue(); 2453 JSValue value = callFrame->r(stackFrame.args[2].int32()).jsValue(); 2454 JSScope::resolvePut(callFrame, base, stackFrame.args[1].identifier(), value, stackFrame.args[3].putToBaseOperation()); 2455 CHECK_FOR_EXCEPTION_AT_END(); 2456} 2457 2458DEFINE_STUB_FUNCTION(EncodedJSValue, op_construct_NotJSConstruct) 2459{ 2460 STUB_INIT_STACK_FRAME(stackFrame); 2461 2462 CallFrame* callFrame = stackFrame.callFrame; 2463 JSValue callee = callFrame->calleeAsValue(); 2464 2465 ConstructData constructData; 2466 ConstructType constructType = getConstructData(callee, constructData); 2467 2468 ASSERT(constructType != ConstructTypeJS); 2469 if (constructType != ConstructTypeHost) { 2470 ASSERT(constructType == ConstructTypeNone); 2471 return throwExceptionFromOpCall<EncodedJSValue>(stackFrame, callFrame, STUB_RETURN_ADDRESS, createNotAConstructorError(callFrame->callerFrame(), callee)); 2472 } 2473 2474 EncodedJSValue returnValue; 2475 { 2476 SamplingTool::CallRecord callRecord(CTI_SAMPLER, true); 2477 returnValue = constructData.native.function(callFrame); 2478 } 2479 2480 if (stackFrame.vm->exception) 2481 return throwExceptionFromOpCall<EncodedJSValue>(stackFrame, callFrame, STUB_RETURN_ADDRESS); 2482 2483 return returnValue; 2484} 2485 2486static JSValue getByVal( 2487 CallFrame* callFrame, JSValue baseValue, JSValue subscript, ReturnAddressPtr returnAddress) 2488{ 2489 if (LIKELY(baseValue.isCell() && subscript.isString())) { 2490 if (JSValue result = baseValue.asCell()->fastGetOwnProperty(callFrame, asString(subscript)->value(callFrame))) 2491 return result; 2492 } 2493 2494 if (subscript.isUInt32()) { 2495 uint32_t i = subscript.asUInt32(); 2496 if (isJSString(baseValue) && asString(baseValue)->canGetIndex(i)) { 2497 ctiPatchCallByReturnAddress(callFrame->codeBlock(), returnAddress, FunctionPtr(cti_op_get_by_val_string)); 2498 return asString(baseValue)->getIndex(callFrame, i); 2499 } 2500 return baseValue.get(callFrame, i); 2501 } 2502 2503 if (isName(subscript)) 2504 return baseValue.get(callFrame, jsCast<NameInstance*>(subscript.asCell())->privateName()); 2505 2506 Identifier property(callFrame, subscript.toString(callFrame)->value(callFrame)); 2507 return baseValue.get(callFrame, property); 2508} 2509 2510DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_val) 2511{ 2512 STUB_INIT_STACK_FRAME(stackFrame); 2513 2514 CallFrame* callFrame = stackFrame.callFrame; 2515 2516 JSValue baseValue = stackFrame.args[0].jsValue(); 2517 JSValue subscript = stackFrame.args[1].jsValue(); 2518 2519 if (baseValue.isObject() && subscript.isInt32()) { 2520 // See if it's worth optimizing this at all. 2521 JSObject* object = asObject(baseValue); 2522 bool didOptimize = false; 2523 2524 unsigned bytecodeOffset = callFrame->bytecodeOffsetForNonDFGCode(); 2525 ASSERT(bytecodeOffset); 2526 ByValInfo& byValInfo = callFrame->codeBlock()->getByValInfo(bytecodeOffset - 1); 2527 ASSERT(!byValInfo.stubRoutine); 2528 2529 if (hasOptimizableIndexing(object->structure())) { 2530 // Attempt to optimize. 2531 JITArrayMode arrayMode = jitArrayModeForStructure(object->structure()); 2532 if (arrayMode != byValInfo.arrayMode) { 2533 JIT::compileGetByVal(&callFrame->vm(), callFrame->codeBlock(), &byValInfo, STUB_RETURN_ADDRESS, arrayMode); 2534 didOptimize = true; 2535 } 2536 } 2537 2538 if (!didOptimize) { 2539 // If we take slow path more than 10 times without patching then make sure we 2540 // never make that mistake again. Or, if we failed to patch and we have some object 2541 // that intercepts indexed get, then don't even wait until 10 times. For cases 2542 // where we see non-index-intercepting objects, this gives 10 iterations worth of 2543 // opportunity for us to observe that the get_by_val may be polymorphic. 2544 if (++byValInfo.slowPathCount >= 10 2545 || object->structure()->typeInfo().interceptsGetOwnPropertySlotByIndexEvenWhenLengthIsNotZero()) { 2546 // Don't ever try to optimize. 2547 RepatchBuffer repatchBuffer(callFrame->codeBlock()); 2548 repatchBuffer.relinkCallerToFunction(STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_val_generic)); 2549 } 2550 } 2551 } 2552 2553 JSValue result = getByVal(callFrame, baseValue, subscript, STUB_RETURN_ADDRESS); 2554 CHECK_FOR_EXCEPTION(); 2555 return JSValue::encode(result); 2556} 2557 2558DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_val_generic) 2559{ 2560 STUB_INIT_STACK_FRAME(stackFrame); 2561 2562 CallFrame* callFrame = stackFrame.callFrame; 2563 2564 JSValue baseValue = stackFrame.args[0].jsValue(); 2565 JSValue subscript = stackFrame.args[1].jsValue(); 2566 2567 JSValue result = getByVal(callFrame, baseValue, subscript, STUB_RETURN_ADDRESS); 2568 CHECK_FOR_EXCEPTION(); 2569 return JSValue::encode(result); 2570} 2571 2572DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_val_string) 2573{ 2574 STUB_INIT_STACK_FRAME(stackFrame); 2575 2576 CallFrame* callFrame = stackFrame.callFrame; 2577 2578 JSValue baseValue = stackFrame.args[0].jsValue(); 2579 JSValue subscript = stackFrame.args[1].jsValue(); 2580 2581 JSValue result; 2582 2583 if (LIKELY(subscript.isUInt32())) { 2584 uint32_t i = subscript.asUInt32(); 2585 if (isJSString(baseValue) && asString(baseValue)->canGetIndex(i)) 2586 result = asString(baseValue)->getIndex(callFrame, i); 2587 else { 2588 result = baseValue.get(callFrame, i); 2589 if (!isJSString(baseValue)) 2590 ctiPatchCallByReturnAddress(callFrame->codeBlock(), STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_val)); 2591 } 2592 } else if (isName(subscript)) 2593 result = baseValue.get(callFrame, jsCast<NameInstance*>(subscript.asCell())->privateName()); 2594 else { 2595 Identifier property(callFrame, subscript.toString(callFrame)->value(callFrame)); 2596 result = baseValue.get(callFrame, property); 2597 } 2598 2599 CHECK_FOR_EXCEPTION_AT_END(); 2600 return JSValue::encode(result); 2601} 2602 2603DEFINE_STUB_FUNCTION(EncodedJSValue, op_sub) 2604{ 2605 STUB_INIT_STACK_FRAME(stackFrame); 2606 2607 JSValue src1 = stackFrame.args[0].jsValue(); 2608 JSValue src2 = stackFrame.args[1].jsValue(); 2609 2610 if (src1.isNumber() && src2.isNumber()) 2611 return JSValue::encode(jsNumber(src1.asNumber() - src2.asNumber())); 2612 2613 CallFrame* callFrame = stackFrame.callFrame; 2614 JSValue result = jsNumber(src1.toNumber(callFrame) - src2.toNumber(callFrame)); 2615 CHECK_FOR_EXCEPTION_AT_END(); 2616 return JSValue::encode(result); 2617} 2618 2619static void putByVal(CallFrame* callFrame, JSValue baseValue, JSValue subscript, JSValue value) 2620{ 2621 if (LIKELY(subscript.isUInt32())) { 2622 uint32_t i = subscript.asUInt32(); 2623 if (baseValue.isObject()) { 2624 JSObject* object = asObject(baseValue); 2625 if (object->canSetIndexQuickly(i)) 2626 object->setIndexQuickly(callFrame->vm(), i, value); 2627 else 2628 object->methodTable()->putByIndex(object, callFrame, i, value, callFrame->codeBlock()->isStrictMode()); 2629 } else 2630 baseValue.putByIndex(callFrame, i, value, callFrame->codeBlock()->isStrictMode()); 2631 } else if (isName(subscript)) { 2632 PutPropertySlot slot(callFrame->codeBlock()->isStrictMode()); 2633 baseValue.put(callFrame, jsCast<NameInstance*>(subscript.asCell())->privateName(), value, slot); 2634 } else { 2635 Identifier property(callFrame, subscript.toString(callFrame)->value(callFrame)); 2636 if (!callFrame->vm().exception) { // Don't put to an object if toString threw an exception. 2637 PutPropertySlot slot(callFrame->codeBlock()->isStrictMode()); 2638 baseValue.put(callFrame, property, value, slot); 2639 } 2640 } 2641} 2642 2643DEFINE_STUB_FUNCTION(void, op_put_by_val) 2644{ 2645 STUB_INIT_STACK_FRAME(stackFrame); 2646 2647 CallFrame* callFrame = stackFrame.callFrame; 2648 2649 JSValue baseValue = stackFrame.args[0].jsValue(); 2650 JSValue subscript = stackFrame.args[1].jsValue(); 2651 JSValue value = stackFrame.args[2].jsValue(); 2652 2653 if (baseValue.isObject() && subscript.isInt32()) { 2654 // See if it's worth optimizing at all. 2655 JSObject* object = asObject(baseValue); 2656 bool didOptimize = false; 2657 2658 unsigned bytecodeOffset = callFrame->bytecodeOffsetForNonDFGCode(); 2659 ASSERT(bytecodeOffset); 2660 ByValInfo& byValInfo = callFrame->codeBlock()->getByValInfo(bytecodeOffset - 1); 2661 ASSERT(!byValInfo.stubRoutine); 2662 2663 if (hasOptimizableIndexing(object->structure())) { 2664 // Attempt to optimize. 2665 JITArrayMode arrayMode = jitArrayModeForStructure(object->structure()); 2666 if (arrayMode != byValInfo.arrayMode) { 2667 JIT::compilePutByVal(&callFrame->vm(), callFrame->codeBlock(), &byValInfo, STUB_RETURN_ADDRESS, arrayMode); 2668 didOptimize = true; 2669 } 2670 } 2671 2672 if (!didOptimize) { 2673 // If we take slow path more than 10 times without patching then make sure we 2674 // never make that mistake again. Or, if we failed to patch and we have some object 2675 // that intercepts indexed get, then don't even wait until 10 times. For cases 2676 // where we see non-index-intercepting objects, this gives 10 iterations worth of 2677 // opportunity for us to observe that the get_by_val may be polymorphic. 2678 if (++byValInfo.slowPathCount >= 10 2679 || object->structure()->typeInfo().interceptsGetOwnPropertySlotByIndexEvenWhenLengthIsNotZero()) { 2680 // Don't ever try to optimize. 2681 RepatchBuffer repatchBuffer(callFrame->codeBlock()); 2682 repatchBuffer.relinkCallerToFunction(STUB_RETURN_ADDRESS, FunctionPtr(cti_op_put_by_val_generic)); 2683 } 2684 } 2685 } 2686 2687 putByVal(callFrame, baseValue, subscript, value); 2688 2689 CHECK_FOR_EXCEPTION_AT_END(); 2690} 2691 2692DEFINE_STUB_FUNCTION(void, op_put_by_val_generic) 2693{ 2694 STUB_INIT_STACK_FRAME(stackFrame); 2695 2696 CallFrame* callFrame = stackFrame.callFrame; 2697 2698 JSValue baseValue = stackFrame.args[0].jsValue(); 2699 JSValue subscript = stackFrame.args[1].jsValue(); 2700 JSValue value = stackFrame.args[2].jsValue(); 2701 2702 putByVal(callFrame, baseValue, subscript, value); 2703 2704 CHECK_FOR_EXCEPTION_AT_END(); 2705} 2706 2707DEFINE_STUB_FUNCTION(EncodedJSValue, op_less) 2708{ 2709 STUB_INIT_STACK_FRAME(stackFrame); 2710 2711 CallFrame* callFrame = stackFrame.callFrame; 2712 JSValue result = jsBoolean(jsLess<true>(callFrame, stackFrame.args[0].jsValue(), stackFrame.args[1].jsValue())); 2713 CHECK_FOR_EXCEPTION_AT_END(); 2714 return JSValue::encode(result); 2715} 2716 2717DEFINE_STUB_FUNCTION(EncodedJSValue, op_lesseq) 2718{ 2719 STUB_INIT_STACK_FRAME(stackFrame); 2720 2721 CallFrame* callFrame = stackFrame.callFrame; 2722 JSValue result = jsBoolean(jsLessEq<true>(callFrame, stackFrame.args[0].jsValue(), stackFrame.args[1].jsValue())); 2723 CHECK_FOR_EXCEPTION_AT_END(); 2724 return JSValue::encode(result); 2725} 2726 2727DEFINE_STUB_FUNCTION(EncodedJSValue, op_greater) 2728{ 2729 STUB_INIT_STACK_FRAME(stackFrame); 2730 2731 CallFrame* callFrame = stackFrame.callFrame; 2732 JSValue result = jsBoolean(jsLess<false>(callFrame, stackFrame.args[1].jsValue(), stackFrame.args[0].jsValue())); 2733 CHECK_FOR_EXCEPTION_AT_END(); 2734 return JSValue::encode(result); 2735} 2736 2737DEFINE_STUB_FUNCTION(EncodedJSValue, op_greatereq) 2738{ 2739 STUB_INIT_STACK_FRAME(stackFrame); 2740 2741 CallFrame* callFrame = stackFrame.callFrame; 2742 JSValue result = jsBoolean(jsLessEq<false>(callFrame, stackFrame.args[1].jsValue(), stackFrame.args[0].jsValue())); 2743 CHECK_FOR_EXCEPTION_AT_END(); 2744 return JSValue::encode(result); 2745} 2746 2747DEFINE_STUB_FUNCTION(void*, op_load_varargs) 2748{ 2749 STUB_INIT_STACK_FRAME(stackFrame); 2750 2751 CallFrame* callFrame = stackFrame.callFrame; 2752 JSStack* stack = stackFrame.stack; 2753 JSValue thisValue = stackFrame.args[0].jsValue(); 2754 JSValue arguments = stackFrame.args[1].jsValue(); 2755 int firstFreeRegister = stackFrame.args[2].int32(); 2756 2757 CallFrame* newCallFrame = loadVarargs(callFrame, stack, thisValue, arguments, firstFreeRegister); 2758 if (!newCallFrame) 2759 VM_THROW_EXCEPTION(); 2760 return newCallFrame; 2761} 2762 2763DEFINE_STUB_FUNCTION(EncodedJSValue, op_negate) 2764{ 2765 STUB_INIT_STACK_FRAME(stackFrame); 2766 2767 JSValue src = stackFrame.args[0].jsValue(); 2768 2769 if (src.isNumber()) 2770 return JSValue::encode(jsNumber(-src.asNumber())); 2771 2772 CallFrame* callFrame = stackFrame.callFrame; 2773 JSValue result = jsNumber(-src.toNumber(callFrame)); 2774 CHECK_FOR_EXCEPTION_AT_END(); 2775 return JSValue::encode(result); 2776} 2777 2778DEFINE_STUB_FUNCTION(EncodedJSValue, op_resolve_base) 2779{ 2780 STUB_INIT_STACK_FRAME(stackFrame); 2781 2782 return JSValue::encode(JSScope::resolveBase(stackFrame.callFrame, stackFrame.args[0].identifier(), false, stackFrame.args[1].resolveOperations(), stackFrame.args[2].putToBaseOperation())); 2783} 2784 2785DEFINE_STUB_FUNCTION(EncodedJSValue, op_resolve_base_strict_put) 2786{ 2787 STUB_INIT_STACK_FRAME(stackFrame); 2788 2789 if (JSValue result = JSScope::resolveBase(stackFrame.callFrame, stackFrame.args[0].identifier(), true, stackFrame.args[1].resolveOperations(), stackFrame.args[2].putToBaseOperation())) 2790 return JSValue::encode(result); 2791 VM_THROW_EXCEPTION(); 2792} 2793 2794DEFINE_STUB_FUNCTION(EncodedJSValue, op_div) 2795{ 2796 STUB_INIT_STACK_FRAME(stackFrame); 2797 2798 JSValue src1 = stackFrame.args[0].jsValue(); 2799 JSValue src2 = stackFrame.args[1].jsValue(); 2800 2801 if (src1.isNumber() && src2.isNumber()) 2802 return JSValue::encode(jsNumber(src1.asNumber() / src2.asNumber())); 2803 2804 CallFrame* callFrame = stackFrame.callFrame; 2805 JSValue result = jsNumber(src1.toNumber(callFrame) / src2.toNumber(callFrame)); 2806 CHECK_FOR_EXCEPTION_AT_END(); 2807 return JSValue::encode(result); 2808} 2809 2810DEFINE_STUB_FUNCTION(EncodedJSValue, op_dec) 2811{ 2812 STUB_INIT_STACK_FRAME(stackFrame); 2813 2814 JSValue v = stackFrame.args[0].jsValue(); 2815 2816 CallFrame* callFrame = stackFrame.callFrame; 2817 JSValue result = jsNumber(v.toNumber(callFrame) - 1); 2818 CHECK_FOR_EXCEPTION_AT_END(); 2819 return JSValue::encode(result); 2820} 2821 2822DEFINE_STUB_FUNCTION(int, op_jless) 2823{ 2824 STUB_INIT_STACK_FRAME(stackFrame); 2825 2826 JSValue src1 = stackFrame.args[0].jsValue(); 2827 JSValue src2 = stackFrame.args[1].jsValue(); 2828 CallFrame* callFrame = stackFrame.callFrame; 2829 2830 bool result = jsLess<true>(callFrame, src1, src2); 2831 CHECK_FOR_EXCEPTION_AT_END(); 2832 return result; 2833} 2834 2835DEFINE_STUB_FUNCTION(int, op_jlesseq) 2836{ 2837 STUB_INIT_STACK_FRAME(stackFrame); 2838 2839 JSValue src1 = stackFrame.args[0].jsValue(); 2840 JSValue src2 = stackFrame.args[1].jsValue(); 2841 CallFrame* callFrame = stackFrame.callFrame; 2842 2843 bool result = jsLessEq<true>(callFrame, src1, src2); 2844 CHECK_FOR_EXCEPTION_AT_END(); 2845 return result; 2846} 2847 2848DEFINE_STUB_FUNCTION(int, op_jgreater) 2849{ 2850 STUB_INIT_STACK_FRAME(stackFrame); 2851 2852 JSValue src1 = stackFrame.args[0].jsValue(); 2853 JSValue src2 = stackFrame.args[1].jsValue(); 2854 CallFrame* callFrame = stackFrame.callFrame; 2855 2856 bool result = jsLess<false>(callFrame, src2, src1); 2857 CHECK_FOR_EXCEPTION_AT_END(); 2858 return result; 2859} 2860 2861DEFINE_STUB_FUNCTION(int, op_jgreatereq) 2862{ 2863 STUB_INIT_STACK_FRAME(stackFrame); 2864 2865 JSValue src1 = stackFrame.args[0].jsValue(); 2866 JSValue src2 = stackFrame.args[1].jsValue(); 2867 CallFrame* callFrame = stackFrame.callFrame; 2868 2869 bool result = jsLessEq<false>(callFrame, src2, src1); 2870 CHECK_FOR_EXCEPTION_AT_END(); 2871 return result; 2872} 2873 2874DEFINE_STUB_FUNCTION(EncodedJSValue, op_not) 2875{ 2876 STUB_INIT_STACK_FRAME(stackFrame); 2877 2878 JSValue src = stackFrame.args[0].jsValue(); 2879 2880 JSValue result = jsBoolean(!src.toBoolean(stackFrame.callFrame)); 2881 CHECK_FOR_EXCEPTION_AT_END(); 2882 return JSValue::encode(result); 2883} 2884 2885DEFINE_STUB_FUNCTION(int, op_jtrue) 2886{ 2887 STUB_INIT_STACK_FRAME(stackFrame); 2888 2889 JSValue src1 = stackFrame.args[0].jsValue(); 2890 2891 bool result = src1.toBoolean(stackFrame.callFrame); 2892 CHECK_FOR_EXCEPTION_AT_END(); 2893 return result; 2894} 2895 2896DEFINE_STUB_FUNCTION(int, op_eq) 2897{ 2898 STUB_INIT_STACK_FRAME(stackFrame); 2899 2900 JSValue src1 = stackFrame.args[0].jsValue(); 2901 JSValue src2 = stackFrame.args[1].jsValue(); 2902 2903#if USE(JSVALUE32_64) 2904 start: 2905 if (src2.isUndefined()) { 2906 return src1.isNull() || 2907 (src1.isCell() && src1.asCell()->structure()->masqueradesAsUndefined(stackFrame.callFrame->lexicalGlobalObject())) 2908 || src1.isUndefined(); 2909 } 2910 2911 if (src2.isNull()) { 2912 return src1.isUndefined() || 2913 (src1.isCell() && src1.asCell()->structure()->masqueradesAsUndefined(stackFrame.callFrame->lexicalGlobalObject())) 2914 || src1.isNull(); 2915 } 2916 2917 if (src1.isInt32()) { 2918 if (src2.isDouble()) 2919 return src1.asInt32() == src2.asDouble(); 2920 double d = src2.toNumber(stackFrame.callFrame); 2921 CHECK_FOR_EXCEPTION(); 2922 return src1.asInt32() == d; 2923 } 2924 2925 if (src1.isDouble()) { 2926 if (src2.isInt32()) 2927 return src1.asDouble() == src2.asInt32(); 2928 double d = src2.toNumber(stackFrame.callFrame); 2929 CHECK_FOR_EXCEPTION(); 2930 return src1.asDouble() == d; 2931 } 2932 2933 if (src1.isTrue()) { 2934 if (src2.isFalse()) 2935 return false; 2936 double d = src2.toNumber(stackFrame.callFrame); 2937 CHECK_FOR_EXCEPTION(); 2938 return d == 1.0; 2939 } 2940 2941 if (src1.isFalse()) { 2942 if (src2.isTrue()) 2943 return false; 2944 double d = src2.toNumber(stackFrame.callFrame); 2945 CHECK_FOR_EXCEPTION(); 2946 return d == 0.0; 2947 } 2948 2949 if (src1.isUndefined()) 2950 return src2.isCell() && src2.asCell()->structure()->masqueradesAsUndefined(stackFrame.callFrame->lexicalGlobalObject()); 2951 2952 if (src1.isNull()) 2953 return src2.isCell() && src2.asCell()->structure()->masqueradesAsUndefined(stackFrame.callFrame->lexicalGlobalObject()); 2954 2955 JSCell* cell1 = src1.asCell(); 2956 2957 if (cell1->isString()) { 2958 if (src2.isInt32()) 2959 return jsToNumber(jsCast<JSString*>(cell1)->value(stackFrame.callFrame)) == src2.asInt32(); 2960 2961 if (src2.isDouble()) 2962 return jsToNumber(jsCast<JSString*>(cell1)->value(stackFrame.callFrame)) == src2.asDouble(); 2963 2964 if (src2.isTrue()) 2965 return jsToNumber(jsCast<JSString*>(cell1)->value(stackFrame.callFrame)) == 1.0; 2966 2967 if (src2.isFalse()) 2968 return jsToNumber(jsCast<JSString*>(cell1)->value(stackFrame.callFrame)) == 0.0; 2969 2970 JSCell* cell2 = src2.asCell(); 2971 if (cell2->isString()) 2972 return jsCast<JSString*>(cell1)->value(stackFrame.callFrame) == jsCast<JSString*>(cell2)->value(stackFrame.callFrame); 2973 2974 src2 = asObject(cell2)->toPrimitive(stackFrame.callFrame); 2975 CHECK_FOR_EXCEPTION(); 2976 goto start; 2977 } 2978 2979 if (src2.isObject()) 2980 return asObject(cell1) == asObject(src2); 2981 src1 = asObject(cell1)->toPrimitive(stackFrame.callFrame); 2982 CHECK_FOR_EXCEPTION(); 2983 goto start; 2984 2985#else // USE(JSVALUE32_64) 2986 CallFrame* callFrame = stackFrame.callFrame; 2987 2988 bool result = JSValue::equalSlowCaseInline(callFrame, src1, src2); 2989 CHECK_FOR_EXCEPTION_AT_END(); 2990 return result; 2991#endif // USE(JSVALUE32_64) 2992} 2993 2994DEFINE_STUB_FUNCTION(int, op_eq_strings) 2995{ 2996#if USE(JSVALUE32_64) 2997 STUB_INIT_STACK_FRAME(stackFrame); 2998 2999 JSString* string1 = stackFrame.args[0].jsString(); 3000 JSString* string2 = stackFrame.args[1].jsString(); 3001 3002 ASSERT(string1->isString()); 3003 ASSERT(string2->isString()); 3004 return string1->value(stackFrame.callFrame) == string2->value(stackFrame.callFrame); 3005#else 3006 UNUSED_PARAM(args); 3007 RELEASE_ASSERT_NOT_REACHED(); 3008 return 0; 3009#endif 3010} 3011 3012DEFINE_STUB_FUNCTION(EncodedJSValue, op_lshift) 3013{ 3014 STUB_INIT_STACK_FRAME(stackFrame); 3015 3016 JSValue val = stackFrame.args[0].jsValue(); 3017 JSValue shift = stackFrame.args[1].jsValue(); 3018 3019 CallFrame* callFrame = stackFrame.callFrame; 3020 JSValue result = jsNumber((val.toInt32(callFrame)) << (shift.toUInt32(callFrame) & 0x1f)); 3021 CHECK_FOR_EXCEPTION_AT_END(); 3022 return JSValue::encode(result); 3023} 3024 3025DEFINE_STUB_FUNCTION(EncodedJSValue, op_bitand) 3026{ 3027 STUB_INIT_STACK_FRAME(stackFrame); 3028 3029 JSValue src1 = stackFrame.args[0].jsValue(); 3030 JSValue src2 = stackFrame.args[1].jsValue(); 3031 3032 ASSERT(!src1.isInt32() || !src2.isInt32()); 3033 CallFrame* callFrame = stackFrame.callFrame; 3034 JSValue result = jsNumber(src1.toInt32(callFrame) & src2.toInt32(callFrame)); 3035 CHECK_FOR_EXCEPTION_AT_END(); 3036 return JSValue::encode(result); 3037} 3038 3039DEFINE_STUB_FUNCTION(EncodedJSValue, op_rshift) 3040{ 3041 STUB_INIT_STACK_FRAME(stackFrame); 3042 3043 JSValue val = stackFrame.args[0].jsValue(); 3044 JSValue shift = stackFrame.args[1].jsValue(); 3045 3046 CallFrame* callFrame = stackFrame.callFrame; 3047 JSValue result = jsNumber((val.toInt32(callFrame)) >> (shift.toUInt32(callFrame) & 0x1f)); 3048 3049 CHECK_FOR_EXCEPTION_AT_END(); 3050 return JSValue::encode(result); 3051} 3052 3053DEFINE_STUB_FUNCTION(EncodedJSValue, op_resolve_with_base) 3054{ 3055 STUB_INIT_STACK_FRAME(stackFrame); 3056 3057 CallFrame* callFrame = stackFrame.callFrame; 3058 JSValue result = JSScope::resolveWithBase(callFrame, stackFrame.args[0].identifier(), &callFrame->registers()[stackFrame.args[1].int32()], stackFrame.args[2].resolveOperations(), stackFrame.args[3].putToBaseOperation()); 3059 CHECK_FOR_EXCEPTION_AT_END(); 3060 return JSValue::encode(result); 3061} 3062 3063DEFINE_STUB_FUNCTION(EncodedJSValue, op_resolve_with_this) 3064{ 3065 STUB_INIT_STACK_FRAME(stackFrame); 3066 3067 CallFrame* callFrame = stackFrame.callFrame; 3068 JSValue result = JSScope::resolveWithThis(callFrame, stackFrame.args[0].identifier(), &callFrame->registers()[stackFrame.args[1].int32()], stackFrame.args[2].resolveOperations()); 3069 CHECK_FOR_EXCEPTION_AT_END(); 3070 return JSValue::encode(result); 3071} 3072 3073DEFINE_STUB_FUNCTION(JSObject*, op_new_func_exp) 3074{ 3075 STUB_INIT_STACK_FRAME(stackFrame); 3076 CallFrame* callFrame = stackFrame.callFrame; 3077 3078 FunctionExecutable* function = stackFrame.args[0].function(); 3079 JSFunction* func = JSFunction::create(callFrame, function, callFrame->scope()); 3080 ASSERT(callFrame->codeBlock()->codeType() != FunctionCode || !callFrame->codeBlock()->needsFullScopeChain() || callFrame->uncheckedR(callFrame->codeBlock()->activationRegister()).jsValue()); 3081 3082 return func; 3083} 3084 3085DEFINE_STUB_FUNCTION(EncodedJSValue, op_mod) 3086{ 3087 STUB_INIT_STACK_FRAME(stackFrame); 3088 3089 JSValue dividendValue = stackFrame.args[0].jsValue(); 3090 JSValue divisorValue = stackFrame.args[1].jsValue(); 3091 3092 CallFrame* callFrame = stackFrame.callFrame; 3093 double d = dividendValue.toNumber(callFrame); 3094 JSValue result = jsNumber(fmod(d, divisorValue.toNumber(callFrame))); 3095 CHECK_FOR_EXCEPTION_AT_END(); 3096 return JSValue::encode(result); 3097} 3098 3099DEFINE_STUB_FUNCTION(EncodedJSValue, op_urshift) 3100{ 3101 STUB_INIT_STACK_FRAME(stackFrame); 3102 3103 JSValue val = stackFrame.args[0].jsValue(); 3104 JSValue shift = stackFrame.args[1].jsValue(); 3105 3106 CallFrame* callFrame = stackFrame.callFrame; 3107 JSValue result = jsNumber((val.toUInt32(callFrame)) >> (shift.toUInt32(callFrame) & 0x1f)); 3108 CHECK_FOR_EXCEPTION_AT_END(); 3109 return JSValue::encode(result); 3110} 3111 3112DEFINE_STUB_FUNCTION(EncodedJSValue, op_bitxor) 3113{ 3114 STUB_INIT_STACK_FRAME(stackFrame); 3115 3116 JSValue src1 = stackFrame.args[0].jsValue(); 3117 JSValue src2 = stackFrame.args[1].jsValue(); 3118 3119 CallFrame* callFrame = stackFrame.callFrame; 3120 3121 JSValue result = jsNumber(src1.toInt32(callFrame) ^ src2.toInt32(callFrame)); 3122 CHECK_FOR_EXCEPTION_AT_END(); 3123 return JSValue::encode(result); 3124} 3125 3126DEFINE_STUB_FUNCTION(JSObject*, op_new_regexp) 3127{ 3128 STUB_INIT_STACK_FRAME(stackFrame); 3129 3130 CallFrame* callFrame = stackFrame.callFrame; 3131 3132 RegExp* regExp = stackFrame.args[0].regExp(); 3133 if (!regExp->isValid()) { 3134 stackFrame.vm->exception = createSyntaxError(callFrame, "Invalid flags supplied to RegExp constructor."); 3135 VM_THROW_EXCEPTION(); 3136 } 3137 3138 return RegExpObject::create(*stackFrame.vm, stackFrame.callFrame->lexicalGlobalObject(), stackFrame.callFrame->lexicalGlobalObject()->regExpStructure(), regExp); 3139} 3140 3141DEFINE_STUB_FUNCTION(EncodedJSValue, op_bitor) 3142{ 3143 STUB_INIT_STACK_FRAME(stackFrame); 3144 3145 JSValue src1 = stackFrame.args[0].jsValue(); 3146 JSValue src2 = stackFrame.args[1].jsValue(); 3147 3148 CallFrame* callFrame = stackFrame.callFrame; 3149 3150 JSValue result = jsNumber(src1.toInt32(callFrame) | src2.toInt32(callFrame)); 3151 CHECK_FOR_EXCEPTION_AT_END(); 3152 return JSValue::encode(result); 3153} 3154 3155DEFINE_STUB_FUNCTION(EncodedJSValue, op_call_eval) 3156{ 3157 STUB_INIT_STACK_FRAME(stackFrame); 3158 3159 CallFrame* callFrame = stackFrame.callFrame; 3160 CallFrame* callerFrame = callFrame->callerFrame(); 3161 ASSERT(callFrame->callerFrame()->codeBlock()->codeType() != FunctionCode 3162 || !callFrame->callerFrame()->codeBlock()->needsFullScopeChain() 3163 || callFrame->callerFrame()->uncheckedR(callFrame->callerFrame()->codeBlock()->activationRegister()).jsValue()); 3164 3165 callFrame->setScope(callerFrame->scope()); 3166 callFrame->setReturnPC(static_cast<Instruction*>((STUB_RETURN_ADDRESS).value())); 3167 callFrame->setCodeBlock(0); 3168 3169 if (!isHostFunction(callFrame->calleeAsValue(), globalFuncEval)) 3170 return JSValue::encode(JSValue()); 3171 3172 JSValue result = eval(callFrame); 3173 if (stackFrame.vm->exception) 3174 return throwExceptionFromOpCall<EncodedJSValue>(stackFrame, callFrame, STUB_RETURN_ADDRESS); 3175 3176 return JSValue::encode(result); 3177} 3178 3179DEFINE_STUB_FUNCTION(void*, op_throw) 3180{ 3181 STUB_INIT_STACK_FRAME(stackFrame); 3182 ExceptionHandler handler = jitThrow(stackFrame.vm, stackFrame.callFrame, stackFrame.args[0].jsValue(), STUB_RETURN_ADDRESS); 3183 STUB_SET_RETURN_ADDRESS(handler.catchRoutine); 3184 return handler.callFrame; 3185} 3186 3187DEFINE_STUB_FUNCTION(JSPropertyNameIterator*, op_get_pnames) 3188{ 3189 STUB_INIT_STACK_FRAME(stackFrame); 3190 3191 CallFrame* callFrame = stackFrame.callFrame; 3192 JSObject* o = stackFrame.args[0].jsObject(); 3193 Structure* structure = o->structure(); 3194 JSPropertyNameIterator* jsPropertyNameIterator = structure->enumerationCache(); 3195 if (!jsPropertyNameIterator || jsPropertyNameIterator->cachedPrototypeChain() != structure->prototypeChain(callFrame)) 3196 jsPropertyNameIterator = JSPropertyNameIterator::create(callFrame, o); 3197 return jsPropertyNameIterator; 3198} 3199 3200DEFINE_STUB_FUNCTION(int, has_property) 3201{ 3202 STUB_INIT_STACK_FRAME(stackFrame); 3203 3204 JSObject* base = stackFrame.args[0].jsObject(); 3205 JSString* property = stackFrame.args[1].jsString(); 3206 int result = base->hasProperty(stackFrame.callFrame, Identifier(stackFrame.callFrame, property->value(stackFrame.callFrame))); 3207 CHECK_FOR_EXCEPTION_AT_END(); 3208 return result; 3209} 3210 3211DEFINE_STUB_FUNCTION(void, op_push_with_scope) 3212{ 3213 STUB_INIT_STACK_FRAME(stackFrame); 3214 3215 JSObject* o = stackFrame.args[0].jsValue().toObject(stackFrame.callFrame); 3216 CHECK_FOR_EXCEPTION_VOID(); 3217 stackFrame.callFrame->setScope(JSWithScope::create(stackFrame.callFrame, o)); 3218} 3219 3220DEFINE_STUB_FUNCTION(void, op_pop_scope) 3221{ 3222 STUB_INIT_STACK_FRAME(stackFrame); 3223 3224 stackFrame.callFrame->setScope(stackFrame.callFrame->scope()->next()); 3225} 3226 3227DEFINE_STUB_FUNCTION(EncodedJSValue, op_typeof) 3228{ 3229 STUB_INIT_STACK_FRAME(stackFrame); 3230 3231 return JSValue::encode(jsTypeStringForValue(stackFrame.callFrame, stackFrame.args[0].jsValue())); 3232} 3233 3234DEFINE_STUB_FUNCTION(EncodedJSValue, op_is_object) 3235{ 3236 STUB_INIT_STACK_FRAME(stackFrame); 3237 3238 return JSValue::encode(jsBoolean(jsIsObjectType(stackFrame.callFrame, stackFrame.args[0].jsValue()))); 3239} 3240 3241DEFINE_STUB_FUNCTION(EncodedJSValue, op_is_function) 3242{ 3243 STUB_INIT_STACK_FRAME(stackFrame); 3244 3245 return JSValue::encode(jsBoolean(jsIsFunctionType(stackFrame.args[0].jsValue()))); 3246} 3247 3248DEFINE_STUB_FUNCTION(EncodedJSValue, op_stricteq) 3249{ 3250 STUB_INIT_STACK_FRAME(stackFrame); 3251 3252 JSValue src1 = stackFrame.args[0].jsValue(); 3253 JSValue src2 = stackFrame.args[1].jsValue(); 3254 3255 bool result = JSValue::strictEqual(stackFrame.callFrame, src1, src2); 3256 CHECK_FOR_EXCEPTION_AT_END(); 3257 return JSValue::encode(jsBoolean(result)); 3258} 3259 3260DEFINE_STUB_FUNCTION(EncodedJSValue, op_to_primitive) 3261{ 3262 STUB_INIT_STACK_FRAME(stackFrame); 3263 3264 return JSValue::encode(stackFrame.args[0].jsValue().toPrimitive(stackFrame.callFrame)); 3265} 3266 3267DEFINE_STUB_FUNCTION(EncodedJSValue, op_strcat) 3268{ 3269 STUB_INIT_STACK_FRAME(stackFrame); 3270 3271 JSValue result = jsString(stackFrame.callFrame, &stackFrame.callFrame->registers()[stackFrame.args[0].int32()], stackFrame.args[1].int32()); 3272 CHECK_FOR_EXCEPTION_AT_END(); 3273 return JSValue::encode(result); 3274} 3275 3276DEFINE_STUB_FUNCTION(EncodedJSValue, op_nstricteq) 3277{ 3278 STUB_INIT_STACK_FRAME(stackFrame); 3279 3280 JSValue src1 = stackFrame.args[0].jsValue(); 3281 JSValue src2 = stackFrame.args[1].jsValue(); 3282 3283 bool result = !JSValue::strictEqual(stackFrame.callFrame, src1, src2); 3284 CHECK_FOR_EXCEPTION_AT_END(); 3285 return JSValue::encode(jsBoolean(result)); 3286} 3287 3288DEFINE_STUB_FUNCTION(EncodedJSValue, op_to_number) 3289{ 3290 STUB_INIT_STACK_FRAME(stackFrame); 3291 3292 JSValue src = stackFrame.args[0].jsValue(); 3293 CallFrame* callFrame = stackFrame.callFrame; 3294 3295 double number = src.toNumber(callFrame); 3296 CHECK_FOR_EXCEPTION_AT_END(); 3297 return JSValue::encode(jsNumber(number)); 3298} 3299 3300DEFINE_STUB_FUNCTION(EncodedJSValue, op_in) 3301{ 3302 STUB_INIT_STACK_FRAME(stackFrame); 3303 3304 CallFrame* callFrame = stackFrame.callFrame; 3305 JSValue baseVal = stackFrame.args[1].jsValue(); 3306 3307 if (!baseVal.isObject()) { 3308 stackFrame.vm->exception = createInvalidParamError(stackFrame.callFrame, "in", baseVal); 3309 VM_THROW_EXCEPTION(); 3310 } 3311 3312 JSValue propName = stackFrame.args[0].jsValue(); 3313 JSObject* baseObj = asObject(baseVal); 3314 3315 uint32_t i; 3316 if (propName.getUInt32(i)) 3317 return JSValue::encode(jsBoolean(baseObj->hasProperty(callFrame, i))); 3318 3319 if (isName(propName)) 3320 return JSValue::encode(jsBoolean(baseObj->hasProperty(callFrame, jsCast<NameInstance*>(propName.asCell())->privateName()))); 3321 3322 Identifier property(callFrame, propName.toString(callFrame)->value(callFrame)); 3323 CHECK_FOR_EXCEPTION(); 3324 return JSValue::encode(jsBoolean(baseObj->hasProperty(callFrame, property))); 3325} 3326 3327DEFINE_STUB_FUNCTION(void, op_push_name_scope) 3328{ 3329 STUB_INIT_STACK_FRAME(stackFrame); 3330 3331 JSNameScope* scope = JSNameScope::create(stackFrame.callFrame, stackFrame.args[0].identifier(), stackFrame.args[1].jsValue(), stackFrame.args[2].int32()); 3332 3333 CallFrame* callFrame = stackFrame.callFrame; 3334 callFrame->setScope(scope); 3335} 3336 3337DEFINE_STUB_FUNCTION(void, op_put_by_index) 3338{ 3339 STUB_INIT_STACK_FRAME(stackFrame); 3340 3341 CallFrame* callFrame = stackFrame.callFrame; 3342 unsigned property = stackFrame.args[1].int32(); 3343 3344 JSValue arrayValue = stackFrame.args[0].jsValue(); 3345 ASSERT(isJSArray(arrayValue)); 3346 asArray(arrayValue)->putDirectIndex(callFrame, property, stackFrame.args[2].jsValue()); 3347} 3348 3349DEFINE_STUB_FUNCTION(void*, op_switch_imm) 3350{ 3351 STUB_INIT_STACK_FRAME(stackFrame); 3352 3353 JSValue scrutinee = stackFrame.args[0].jsValue(); 3354 unsigned tableIndex = stackFrame.args[1].int32(); 3355 CallFrame* callFrame = stackFrame.callFrame; 3356 CodeBlock* codeBlock = callFrame->codeBlock(); 3357 3358 if (scrutinee.isInt32()) 3359 return codeBlock->immediateSwitchJumpTable(tableIndex).ctiForValue(scrutinee.asInt32()).executableAddress(); 3360 if (scrutinee.isDouble() && scrutinee.asDouble() == static_cast<int32_t>(scrutinee.asDouble())) 3361 return codeBlock->immediateSwitchJumpTable(tableIndex).ctiForValue(static_cast<int32_t>(scrutinee.asDouble())).executableAddress(); 3362 return codeBlock->immediateSwitchJumpTable(tableIndex).ctiDefault.executableAddress(); 3363} 3364 3365DEFINE_STUB_FUNCTION(void*, op_switch_char) 3366{ 3367 STUB_INIT_STACK_FRAME(stackFrame); 3368 3369 JSValue scrutinee = stackFrame.args[0].jsValue(); 3370 unsigned tableIndex = stackFrame.args[1].int32(); 3371 CallFrame* callFrame = stackFrame.callFrame; 3372 CodeBlock* codeBlock = callFrame->codeBlock(); 3373 3374 void* result = codeBlock->characterSwitchJumpTable(tableIndex).ctiDefault.executableAddress(); 3375 3376 if (scrutinee.isString()) { 3377 StringImpl* value = asString(scrutinee)->value(callFrame).impl(); 3378 if (value->length() == 1) 3379 result = codeBlock->characterSwitchJumpTable(tableIndex).ctiForValue((*value)[0]).executableAddress(); 3380 } 3381 3382 CHECK_FOR_EXCEPTION_AT_END(); 3383 return result; 3384} 3385 3386DEFINE_STUB_FUNCTION(void*, op_switch_string) 3387{ 3388 STUB_INIT_STACK_FRAME(stackFrame); 3389 3390 JSValue scrutinee = stackFrame.args[0].jsValue(); 3391 unsigned tableIndex = stackFrame.args[1].int32(); 3392 CallFrame* callFrame = stackFrame.callFrame; 3393 CodeBlock* codeBlock = callFrame->codeBlock(); 3394 3395 void* result = codeBlock->stringSwitchJumpTable(tableIndex).ctiDefault.executableAddress(); 3396 3397 if (scrutinee.isString()) { 3398 StringImpl* value = asString(scrutinee)->value(callFrame).impl(); 3399 result = codeBlock->stringSwitchJumpTable(tableIndex).ctiForValue(value).executableAddress(); 3400 } 3401 3402 CHECK_FOR_EXCEPTION_AT_END(); 3403 return result; 3404} 3405 3406DEFINE_STUB_FUNCTION(EncodedJSValue, op_del_by_val) 3407{ 3408 STUB_INIT_STACK_FRAME(stackFrame); 3409 3410 CallFrame* callFrame = stackFrame.callFrame; 3411 3412 JSValue baseValue = stackFrame.args[0].jsValue(); 3413 JSObject* baseObj = baseValue.toObject(callFrame); // may throw 3414 3415 JSValue subscript = stackFrame.args[1].jsValue(); 3416 bool result; 3417 uint32_t i; 3418 if (subscript.getUInt32(i)) 3419 result = baseObj->methodTable()->deletePropertyByIndex(baseObj, callFrame, i); 3420 else if (isName(subscript)) 3421 result = baseObj->methodTable()->deleteProperty(baseObj, callFrame, jsCast<NameInstance*>(subscript.asCell())->privateName()); 3422 else { 3423 CHECK_FOR_EXCEPTION(); 3424 Identifier property(callFrame, subscript.toString(callFrame)->value(callFrame)); 3425 CHECK_FOR_EXCEPTION(); 3426 result = baseObj->methodTable()->deleteProperty(baseObj, callFrame, property); 3427 } 3428 3429 if (!result && callFrame->codeBlock()->isStrictMode()) 3430 stackFrame.vm->exception = createTypeError(stackFrame.callFrame, "Unable to delete property."); 3431 3432 CHECK_FOR_EXCEPTION_AT_END(); 3433 return JSValue::encode(jsBoolean(result)); 3434} 3435 3436DEFINE_STUB_FUNCTION(void, op_put_getter_setter) 3437{ 3438 STUB_INIT_STACK_FRAME(stackFrame); 3439 3440 CallFrame* callFrame = stackFrame.callFrame; 3441 3442 ASSERT(stackFrame.args[0].jsValue().isObject()); 3443 JSObject* baseObj = asObject(stackFrame.args[0].jsValue()); 3444 3445 GetterSetter* accessor = GetterSetter::create(callFrame); 3446 3447 JSValue getter = stackFrame.args[2].jsValue(); 3448 JSValue setter = stackFrame.args[3].jsValue(); 3449 ASSERT(getter.isObject() || getter.isUndefined()); 3450 ASSERT(setter.isObject() || setter.isUndefined()); 3451 ASSERT(getter.isObject() || setter.isObject()); 3452 3453 if (!getter.isUndefined()) 3454 accessor->setGetter(callFrame->vm(), asObject(getter)); 3455 if (!setter.isUndefined()) 3456 accessor->setSetter(callFrame->vm(), asObject(setter)); 3457 baseObj->putDirectAccessor(callFrame, stackFrame.args[1].identifier(), accessor, Accessor); 3458} 3459 3460DEFINE_STUB_FUNCTION(void, op_throw_static_error) 3461{ 3462 STUB_INIT_STACK_FRAME(stackFrame); 3463 3464 CallFrame* callFrame = stackFrame.callFrame; 3465 String message = stackFrame.args[0].jsValue().toString(callFrame)->value(callFrame); 3466 if (stackFrame.args[1].asInt32) 3467 stackFrame.vm->exception = createReferenceError(callFrame, message); 3468 else 3469 stackFrame.vm->exception = createTypeError(callFrame, message); 3470 VM_THROW_EXCEPTION_AT_END(); 3471} 3472 3473DEFINE_STUB_FUNCTION(void, op_debug) 3474{ 3475 STUB_INIT_STACK_FRAME(stackFrame); 3476 3477 CallFrame* callFrame = stackFrame.callFrame; 3478 3479 int debugHookID = stackFrame.args[0].int32(); 3480 int firstLine = stackFrame.args[1].int32(); 3481 int lastLine = stackFrame.args[2].int32(); 3482 int column = stackFrame.args[3].int32(); 3483 3484 stackFrame.vm->interpreter->debug(callFrame, static_cast<DebugHookID>(debugHookID), firstLine, lastLine, column); 3485} 3486 3487DEFINE_STUB_FUNCTION(void*, vm_throw) 3488{ 3489 STUB_INIT_STACK_FRAME(stackFrame); 3490 VM* vm = stackFrame.vm; 3491 ExceptionHandler handler = jitThrow(vm, stackFrame.callFrame, vm->exception, vm->exceptionLocation); 3492 STUB_SET_RETURN_ADDRESS(handler.catchRoutine); 3493 return handler.callFrame; 3494} 3495 3496DEFINE_STUB_FUNCTION(EncodedJSValue, to_object) 3497{ 3498 STUB_INIT_STACK_FRAME(stackFrame); 3499 3500 CallFrame* callFrame = stackFrame.callFrame; 3501 return JSValue::encode(stackFrame.args[0].jsValue().toObject(callFrame)); 3502} 3503 3504} // namespace JSC 3505 3506#endif // ENABLE(JIT) 3507