1 /* 2 * Copyright (C) 2008, 2009 Apple Inc. All rights reserved. 3 * Copyright (C) 2008 Cameron Zwarich <cwzwarich (at) uwaterloo.ca> 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of 15 * its contributors may be used to endorse or promote products derived 16 * from this software without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY 19 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 20 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY 22 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 23 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 24 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 25 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 */ 29 30 #include "config.h" 31 #include "JITStubs.h" 32 33 #if ENABLE(JIT) 34 35 #include "Arguments.h" 36 #include "CallFrame.h" 37 #include "CodeBlock.h" 38 #include "Collector.h" 39 #include "Debugger.h" 40 #include "ExceptionHelpers.h" 41 #include "GlobalEvalFunction.h" 42 #include "JIT.h" 43 #include "JSActivation.h" 44 #include "JSArray.h" 45 #include "JSByteArray.h" 46 #include "JSFunction.h" 47 #include "JSNotAnObject.h" 48 #include "JSPropertyNameIterator.h" 49 #include "JSStaticScopeObject.h" 50 #include "JSString.h" 51 #include "ObjectPrototype.h" 52 #include "Operations.h" 53 #include "Parser.h" 54 #include "Profiler.h" 55 #include "RegExpObject.h" 56 #include "RegExpPrototype.h" 57 #include "Register.h" 58 #include "SamplingTool.h" 59 #include <wtf/StdLibExtras.h> 60 #include <stdarg.h> 61 #include <stdio.h> 62 63 using namespace std; 64 65 namespace JSC { 66 67 #if OS(DARWIN) || OS(WINDOWS) 68 #define SYMBOL_STRING(name) "_" #name 69 #else 70 #define SYMBOL_STRING(name) #name 71 #endif 72 73 #if OS(IPHONE_OS) 74 #define THUMB_FUNC_PARAM(name) SYMBOL_STRING(name) 75 #else 76 #define THUMB_FUNC_PARAM(name) 77 #endif 78 79 #if OS(LINUX) && CPU(X86_64) 80 #define SYMBOL_STRING_RELOCATION(name) #name "@plt" 81 #else 82 #define SYMBOL_STRING_RELOCATION(name) SYMBOL_STRING(name) 83 #endif 84 85 #if OS(DARWIN) 86 // Mach-O platform 87 #define HIDE_SYMBOL(name) ".private_extern _" #name 88 #elif OS(AIX) 89 // IBM's own file format 90 #define HIDE_SYMBOL(name) ".lglobl " #name 91 #elif OS(LINUX) \ 92 || OS(FREEBSD) \ 93 || OS(OPENBSD) \ 94 || OS(SOLARIS) \ 95 || (OS(HPUX) && CPU(IA64)) \ 96 || OS(SYMBIAN) \ 97 || OS(NETBSD) 98 // ELF platform 99 #define HIDE_SYMBOL(name) ".hidden " #name 100 #else 101 #define HIDE_SYMBOL(name) 102 #endif 103 104 #if USE(JSVALUE32_64) 105 106 #if COMPILER(GCC) && CPU(X86) 107 108 // These ASSERTs remind you that, if you change the layout of JITStackFrame, you 109 // need to change the assembly trampolines below to match. 110 COMPILE_ASSERT(offsetof(struct JITStackFrame, code) % 16 == 0x0, JITStackFrame_maintains_16byte_stack_alignment); 111 COMPILE_ASSERT(offsetof(struct JITStackFrame, savedEBX) == 0x3c, JITStackFrame_stub_argument_space_matches_ctiTrampoline); 112 COMPILE_ASSERT(offsetof(struct JITStackFrame, callFrame) == 0x58, JITStackFrame_callFrame_offset_matches_ctiTrampoline); 113 COMPILE_ASSERT(offsetof(struct JITStackFrame, code) == 0x50, JITStackFrame_code_offset_matches_ctiTrampoline); 114 115 asm volatile ( 116 ".text\n" 117 ".globl " SYMBOL_STRING(ctiTrampoline) "\n" 118 HIDE_SYMBOL(ctiTrampoline) "\n" 119 SYMBOL_STRING(ctiTrampoline) ":" "\n" 120 "pushl %ebp" "\n" 121 "movl %esp, %ebp" "\n" 122 "pushl %esi" "\n" 123 "pushl %edi" "\n" 124 "pushl %ebx" "\n" 125 "subl $0x3c, %esp" "\n" 126 "movl $512, %esi" "\n" 127 "movl 0x58(%esp), %edi" "\n" 128 "call *0x50(%esp)" "\n" 129 "addl $0x3c, %esp" "\n" 130 "popl %ebx" "\n" 131 "popl %edi" "\n" 132 "popl %esi" "\n" 133 "popl %ebp" "\n" 134 "ret" "\n" 135 ); 136 137 asm volatile ( 138 ".globl " SYMBOL_STRING(ctiVMThrowTrampoline) "\n" 139 HIDE_SYMBOL(ctiVMThrowTrampoline) "\n" 140 SYMBOL_STRING(ctiVMThrowTrampoline) ":" "\n" 141 #if !USE(JIT_STUB_ARGUMENT_VA_LIST) 142 "movl %esp, %ecx" "\n" 143 #endif 144 "call " SYMBOL_STRING_RELOCATION(cti_vm_throw) "\n" 145 "addl $0x3c, %esp" "\n" 146 "popl %ebx" "\n" 147 "popl %edi" "\n" 148 "popl %esi" "\n" 149 "popl %ebp" "\n" 150 "ret" "\n" 151 ); 152 153 asm volatile ( 154 ".globl " SYMBOL_STRING(ctiOpThrowNotCaught) "\n" 155 HIDE_SYMBOL(ctiOpThrowNotCaught) "\n" 156 SYMBOL_STRING(ctiOpThrowNotCaught) ":" "\n" 157 "addl $0x3c, %esp" "\n" 158 "popl %ebx" "\n" 159 "popl %edi" "\n" 160 "popl %esi" "\n" 161 "popl %ebp" "\n" 162 "ret" "\n" 163 ); 164 165 #elif COMPILER(GCC) && CPU(X86_64) 166 167 #if USE(JIT_STUB_ARGUMENT_VA_LIST) 168 #error "JIT_STUB_ARGUMENT_VA_LIST not supported on x86-64." 169 #endif 170 171 // These ASSERTs remind you that, if you change the layout of JITStackFrame, you 172 // need to change the assembly trampolines below to match. 173 COMPILE_ASSERT(offsetof(struct JITStackFrame, code) % 32 == 0x0, JITStackFrame_maintains_32byte_stack_alignment); 174 COMPILE_ASSERT(offsetof(struct JITStackFrame, savedRBX) == 0x48, JITStackFrame_stub_argument_space_matches_ctiTrampoline); 175 COMPILE_ASSERT(offsetof(struct JITStackFrame, callFrame) == 0x90, JITStackFrame_callFrame_offset_matches_ctiTrampoline); 176 COMPILE_ASSERT(offsetof(struct JITStackFrame, code) == 0x80, JITStackFrame_code_offset_matches_ctiTrampoline); 177 178 asm volatile ( 179 ".globl " SYMBOL_STRING(ctiTrampoline) "\n" 180 HIDE_SYMBOL(ctiTrampoline) "\n" 181 SYMBOL_STRING(ctiTrampoline) ":" "\n" 182 "pushq %rbp" "\n" 183 "movq %rsp, %rbp" "\n" 184 "pushq %r12" "\n" 185 "pushq %r13" "\n" 186 "pushq %r14" "\n" 187 "pushq %r15" "\n" 188 "pushq %rbx" "\n" 189 "subq $0x48, %rsp" "\n" 190 "movq $512, %r12" "\n" 191 "movq $0xFFFF000000000000, %r14" "\n" 192 "movq $0xFFFF000000000002, %r15" "\n" 193 "movq 0x90(%rsp), %r13" "\n" 194 "call *0x80(%rsp)" "\n" 195 "addq $0x48, %rsp" "\n" 196 "popq %rbx" "\n" 197 "popq %r15" "\n" 198 "popq %r14" "\n" 199 "popq %r13" "\n" 200 "popq %r12" "\n" 201 "popq %rbp" "\n" 202 "ret" "\n" 203 ); 204 205 asm volatile ( 206 ".globl " SYMBOL_STRING(ctiVMThrowTrampoline) "\n" 207 HIDE_SYMBOL(ctiVMThrowTrampoline) "\n" 208 SYMBOL_STRING(ctiVMThrowTrampoline) ":" "\n" 209 "movq %rsp, %rdi" "\n" 210 "call " SYMBOL_STRING_RELOCATION(cti_vm_throw) "\n" 211 "addq $0x48, %rsp" "\n" 212 "popq %rbx" "\n" 213 "popq %r15" "\n" 214 "popq %r14" "\n" 215 "popq %r13" "\n" 216 "popq %r12" "\n" 217 "popq %rbp" "\n" 218 "ret" "\n" 219 ); 220 221 asm volatile ( 222 ".globl " SYMBOL_STRING(ctiOpThrowNotCaught) "\n" 223 HIDE_SYMBOL(ctiOpThrowNotCaught) "\n" 224 SYMBOL_STRING(ctiOpThrowNotCaught) ":" "\n" 225 "addq $0x48, %rsp" "\n" 226 "popq %rbx" "\n" 227 "popq %r15" "\n" 228 "popq %r14" "\n" 229 "popq %r13" "\n" 230 "popq %r12" "\n" 231 "popq %rbp" "\n" 232 "ret" "\n" 233 ); 234 235 #elif COMPILER(GCC) && CPU(ARM_THUMB2) 236 237 #if USE(JIT_STUB_ARGUMENT_VA_LIST) 238 #error "JIT_STUB_ARGUMENT_VA_LIST not supported on ARMv7." 239 #endif 240 241 asm volatile ( 242 ".text" "\n" 243 ".align 2" "\n" 244 ".globl " SYMBOL_STRING(ctiTrampoline) "\n" 245 HIDE_SYMBOL(ctiTrampoline) "\n" 246 ".thumb" "\n" 247 ".thumb_func " THUMB_FUNC_PARAM(ctiTrampoline) "\n" 248 SYMBOL_STRING(ctiTrampoline) ":" "\n" 249 "sub sp, sp, #0x3c" "\n" 250 "str lr, [sp, #0x20]" "\n" 251 "str r4, [sp, #0x24]" "\n" 252 "str r5, [sp, #0x28]" "\n" 253 "str r6, [sp, #0x2c]" "\n" 254 "str r1, [sp, #0x30]" "\n" 255 "str r2, [sp, #0x34]" "\n" 256 "str r3, [sp, #0x38]" "\n" 257 "cpy r5, r2" "\n" 258 "mov r6, #512" "\n" 259 "blx r0" "\n" 260 "ldr r6, [sp, #0x2c]" "\n" 261 "ldr r5, [sp, #0x28]" "\n" 262 "ldr r4, [sp, #0x24]" "\n" 263 "ldr lr, [sp, #0x20]" "\n" 264 "add sp, sp, #0x3c" "\n" 265 "bx lr" "\n" 266 ); 267 268 asm volatile ( 269 ".text" "\n" 270 ".align 2" "\n" 271 ".globl " SYMBOL_STRING(ctiVMThrowTrampoline) "\n" 272 HIDE_SYMBOL(ctiVMThrowTrampoline) "\n" 273 ".thumb" "\n" 274 ".thumb_func " THUMB_FUNC_PARAM(ctiVMThrowTrampoline) "\n" 275 SYMBOL_STRING(ctiVMThrowTrampoline) ":" "\n" 276 "cpy r0, sp" "\n" 277 "bl " SYMBOL_STRING_RELOCATION(cti_vm_throw) "\n" 278 "ldr r6, [sp, #0x2c]" "\n" 279 "ldr r5, [sp, #0x28]" "\n" 280 "ldr r4, [sp, #0x24]" "\n" 281 "ldr lr, [sp, #0x20]" "\n" 282 "add sp, sp, #0x3c" "\n" 283 "bx lr" "\n" 284 ); 285 286 asm volatile ( 287 ".text" "\n" 288 ".align 2" "\n" 289 ".globl " SYMBOL_STRING(ctiOpThrowNotCaught) "\n" 290 ".thumb" "\n" 291 ".thumb_func " THUMB_FUNC_PARAM(ctiOpThrowNotCaught) "\n" 292 SYMBOL_STRING(ctiOpThrowNotCaught) ":" "\n" 293 "ldr r6, [sp, #0x2c]" "\n" 294 "ldr r5, [sp, #0x28]" "\n" 295 "ldr r4, [sp, #0x24]" "\n" 296 "ldr lr, [sp, #0x20]" "\n" 297 "add sp, sp, #0x3c" "\n" 298 "bx lr" "\n" 299 ); 300 301 #elif COMPILER(GCC) && CPU(ARM_TRADITIONAL) 302 303 asm volatile ( 304 ".globl " SYMBOL_STRING(ctiTrampoline) "\n" 305 SYMBOL_STRING(ctiTrampoline) ":" "\n" 306 "stmdb sp!, {r1-r3}" "\n" 307 "stmdb sp!, {r4-r8, lr}" "\n" 308 "sub sp, sp, #68" "\n" 309 "mov r4, r2" "\n" 310 "mov r5, #512" "\n" 311 // r0 contains the code 312 "mov lr, pc" "\n" 313 "mov pc, r0" "\n" 314 "add sp, sp, #68" "\n" 315 "ldmia sp!, {r4-r8, lr}" "\n" 316 "add sp, sp, #12" "\n" 317 "mov pc, lr" "\n" 318 ); 319 320 asm volatile ( 321 ".globl " SYMBOL_STRING(ctiVMThrowTrampoline) "\n" 322 SYMBOL_STRING(ctiVMThrowTrampoline) ":" "\n" 323 "mov r0, sp" "\n" 324 "bl " SYMBOL_STRING(cti_vm_throw) "\n" 325 326 // Both has the same return sequence 327 ".globl " SYMBOL_STRING(ctiOpThrowNotCaught) "\n" 328 SYMBOL_STRING(ctiOpThrowNotCaught) ":" "\n" 329 "add sp, sp, #68" "\n" 330 "ldmia sp!, {r4-r8, lr}" "\n" 331 "add sp, sp, #12" "\n" 332 "mov pc, lr" "\n" 333 ); 334 335 #elif COMPILER(MSVC) && CPU(X86) 336 337 #if USE(JIT_STUB_ARGUMENT_VA_LIST) 338 #error "JIT_STUB_ARGUMENT_VA_LIST configuration not supported on MSVC." 339 #endif 340 341 // These ASSERTs remind you that, if you change the layout of JITStackFrame, you 342 // need to change the assembly trampolines below to match. 343 COMPILE_ASSERT(offsetof(struct JITStackFrame, code) % 16 == 0x0, JITStackFrame_maintains_16byte_stack_alignment); 344 COMPILE_ASSERT(offsetof(struct JITStackFrame, savedEBX) == 0x3c, JITStackFrame_stub_argument_space_matches_ctiTrampoline); 345 COMPILE_ASSERT(offsetof(struct JITStackFrame, callFrame) == 0x58, JITStackFrame_callFrame_offset_matches_ctiTrampoline); 346 COMPILE_ASSERT(offsetof(struct JITStackFrame, code) == 0x50, JITStackFrame_code_offset_matches_ctiTrampoline); 347 348 extern "C" { 349 350 __declspec(naked) EncodedJSValue ctiTrampoline(void* code, RegisterFile*, CallFrame*, JSValue* exception, Profiler**, JSGlobalData*) 351 { 352 __asm { 353 push ebp; 354 mov ebp, esp; 355 push esi; 356 push edi; 357 push ebx; 358 sub esp, 0x3c; 359 mov esi, 512; 360 mov ecx, esp; 361 mov edi, [esp + 0x58]; 362 call [esp + 0x50]; 363 add esp, 0x3c; 364 pop ebx; 365 pop edi; 366 pop esi; 367 pop ebp; 368 ret; 369 } 370 } 371 372 __declspec(naked) void ctiVMThrowTrampoline() 373 { 374 __asm { 375 mov ecx, esp; 376 call cti_vm_throw; 377 add esp, 0x3c; 378 pop ebx; 379 pop edi; 380 pop esi; 381 pop ebp; 382 ret; 383 } 384 } 385 386 __declspec(naked) void ctiOpThrowNotCaught() 387 { 388 __asm { 389 add esp, 0x3c; 390 pop ebx; 391 pop edi; 392 pop esi; 393 pop ebp; 394 ret; 395 } 396 } 397 } 398 399 #else 400 #error "JIT not supported on this platform." 401 #endif 402 403 #else // USE(JSVALUE32_64) 404 405 #if COMPILER(GCC) && CPU(X86) 406 407 // These ASSERTs remind you that, if you change the layout of JITStackFrame, you 408 // need to change the assembly trampolines below to match. 409 COMPILE_ASSERT(offsetof(struct JITStackFrame, callFrame) == 0x38, JITStackFrame_callFrame_offset_matches_ctiTrampoline); 410 COMPILE_ASSERT(offsetof(struct JITStackFrame, code) == 0x30, JITStackFrame_code_offset_matches_ctiTrampoline); 411 COMPILE_ASSERT(offsetof(struct JITStackFrame, savedEBX) == 0x1c, JITStackFrame_stub_argument_space_matches_ctiTrampoline); 412 413 asm volatile ( 414 ".text\n" 415 ".globl " SYMBOL_STRING(ctiTrampoline) "\n" 416 HIDE_SYMBOL(ctiTrampoline) "\n" 417 SYMBOL_STRING(ctiTrampoline) ":" "\n" 418 "pushl %ebp" "\n" 419 "movl %esp, %ebp" "\n" 420 "pushl %esi" "\n" 421 "pushl %edi" "\n" 422 "pushl %ebx" "\n" 423 "subl $0x1c, %esp" "\n" 424 "movl $512, %esi" "\n" 425 "movl 0x38(%esp), %edi" "\n" 426 "call *0x30(%esp)" "\n" 427 "addl $0x1c, %esp" "\n" 428 "popl %ebx" "\n" 429 "popl %edi" "\n" 430 "popl %esi" "\n" 431 "popl %ebp" "\n" 432 "ret" "\n" 433 ); 434 435 asm volatile ( 436 ".globl " SYMBOL_STRING(ctiVMThrowTrampoline) "\n" 437 HIDE_SYMBOL(ctiVMThrowTrampoline) "\n" 438 SYMBOL_STRING(ctiVMThrowTrampoline) ":" "\n" 439 #if !USE(JIT_STUB_ARGUMENT_VA_LIST) 440 "movl %esp, %ecx" "\n" 441 #endif 442 "call " SYMBOL_STRING_RELOCATION(cti_vm_throw) "\n" 443 "addl $0x1c, %esp" "\n" 444 "popl %ebx" "\n" 445 "popl %edi" "\n" 446 "popl %esi" "\n" 447 "popl %ebp" "\n" 448 "ret" "\n" 449 ); 450 451 asm volatile ( 452 ".globl " SYMBOL_STRING(ctiOpThrowNotCaught) "\n" 453 HIDE_SYMBOL(ctiOpThrowNotCaught) "\n" 454 SYMBOL_STRING(ctiOpThrowNotCaught) ":" "\n" 455 "addl $0x1c, %esp" "\n" 456 "popl %ebx" "\n" 457 "popl %edi" "\n" 458 "popl %esi" "\n" 459 "popl %ebp" "\n" 460 "ret" "\n" 461 ); 462 463 #elif COMPILER(GCC) && CPU(X86_64) 464 465 #if USE(JIT_STUB_ARGUMENT_VA_LIST) 466 #error "JIT_STUB_ARGUMENT_VA_LIST not supported on x86-64." 467 #endif 468 469 // These ASSERTs remind you that, if you change the layout of JITStackFrame, you 470 // need to change the assembly trampolines below to match. 471 COMPILE_ASSERT(offsetof(struct JITStackFrame, callFrame) == 0x58, JITStackFrame_callFrame_offset_matches_ctiTrampoline); 472 COMPILE_ASSERT(offsetof(struct JITStackFrame, code) == 0x48, JITStackFrame_code_offset_matches_ctiTrampoline); 473 COMPILE_ASSERT(offsetof(struct JITStackFrame, savedRBX) == 0x78, JITStackFrame_stub_argument_space_matches_ctiTrampoline); 474 475 asm volatile ( 476 ".text\n" 477 ".globl " SYMBOL_STRING(ctiTrampoline) "\n" 478 HIDE_SYMBOL(ctiTrampoline) "\n" 479 SYMBOL_STRING(ctiTrampoline) ":" "\n" 480 "pushq %rbp" "\n" 481 "movq %rsp, %rbp" "\n" 482 "pushq %r12" "\n" 483 "pushq %r13" "\n" 484 "pushq %r14" "\n" 485 "pushq %r15" "\n" 486 "pushq %rbx" "\n" 487 // Form the JIT stubs area 488 "pushq %r9" "\n" 489 "pushq %r8" "\n" 490 "pushq %rcx" "\n" 491 "pushq %rdx" "\n" 492 "pushq %rsi" "\n" 493 "pushq %rdi" "\n" 494 "subq $0x48, %rsp" "\n" 495 "movq $512, %r12" "\n" 496 "movq $0xFFFF000000000000, %r14" "\n" 497 "movq $0xFFFF000000000002, %r15" "\n" 498 "movq %rdx, %r13" "\n" 499 "call *%rdi" "\n" 500 "addq $0x78, %rsp" "\n" 501 "popq %rbx" "\n" 502 "popq %r15" "\n" 503 "popq %r14" "\n" 504 "popq %r13" "\n" 505 "popq %r12" "\n" 506 "popq %rbp" "\n" 507 "ret" "\n" 508 ); 509 510 asm volatile ( 511 ".globl " SYMBOL_STRING(ctiVMThrowTrampoline) "\n" 512 HIDE_SYMBOL(ctiVMThrowTrampoline) "\n" 513 SYMBOL_STRING(ctiVMThrowTrampoline) ":" "\n" 514 "movq %rsp, %rdi" "\n" 515 "call " SYMBOL_STRING_RELOCATION(cti_vm_throw) "\n" 516 "addq $0x78, %rsp" "\n" 517 "popq %rbx" "\n" 518 "popq %r15" "\n" 519 "popq %r14" "\n" 520 "popq %r13" "\n" 521 "popq %r12" "\n" 522 "popq %rbp" "\n" 523 "ret" "\n" 524 ); 525 526 asm volatile ( 527 ".globl " SYMBOL_STRING(ctiOpThrowNotCaught) "\n" 528 HIDE_SYMBOL(ctiOpThrowNotCaught) "\n" 529 SYMBOL_STRING(ctiOpThrowNotCaught) ":" "\n" 530 "addq $0x78, %rsp" "\n" 531 "popq %rbx" "\n" 532 "popq %r15" "\n" 533 "popq %r14" "\n" 534 "popq %r13" "\n" 535 "popq %r12" "\n" 536 "popq %rbp" "\n" 537 "ret" "\n" 538 ); 539 540 #elif COMPILER(GCC) && CPU(ARM_THUMB2) 541 542 #if USE(JIT_STUB_ARGUMENT_VA_LIST) 543 #error "JIT_STUB_ARGUMENT_VA_LIST not supported on ARMv7." 544 #endif 545 546 asm volatile ( 547 ".text" "\n" 548 ".align 2" "\n" 549 ".globl " SYMBOL_STRING(ctiTrampoline) "\n" 550 HIDE_SYMBOL(ctiTrampoline) "\n" 551 ".thumb" "\n" 552 ".thumb_func " THUMB_FUNC_PARAM(ctiTrampoline) "\n" 553 SYMBOL_STRING(ctiTrampoline) ":" "\n" 554 "sub sp, sp, #0x40" "\n" 555 "str lr, [sp, #0x20]" "\n" 556 "str r4, [sp, #0x24]" "\n" 557 "str r5, [sp, #0x28]" "\n" 558 "str r6, [sp, #0x2c]" "\n" 559 "str r1, [sp, #0x30]" "\n" 560 "str r2, [sp, #0x34]" "\n" 561 "str r3, [sp, #0x38]" "\n" 562 "cpy r5, r2" "\n" 563 "mov r6, #512" "\n" 564 "blx r0" "\n" 565 "ldr r6, [sp, #0x2c]" "\n" 566 "ldr r5, [sp, #0x28]" "\n" 567 "ldr r4, [sp, #0x24]" "\n" 568 "ldr lr, [sp, #0x20]" "\n" 569 "add sp, sp, #0x40" "\n" 570 "bx lr" "\n" 571 ); 572 573 asm volatile ( 574 ".text" "\n" 575 ".align 2" "\n" 576 ".globl " SYMBOL_STRING(ctiVMThrowTrampoline) "\n" 577 HIDE_SYMBOL(ctiVMThrowTrampoline) "\n" 578 ".thumb" "\n" 579 ".thumb_func " THUMB_FUNC_PARAM(ctiVMThrowTrampoline) "\n" 580 SYMBOL_STRING(ctiVMThrowTrampoline) ":" "\n" 581 "cpy r0, sp" "\n" 582 "bl " SYMBOL_STRING_RELOCATION(cti_vm_throw) "\n" 583 "ldr r6, [sp, #0x2c]" "\n" 584 "ldr r5, [sp, #0x28]" "\n" 585 "ldr r4, [sp, #0x24]" "\n" 586 "ldr lr, [sp, #0x20]" "\n" 587 "add sp, sp, #0x40" "\n" 588 "bx lr" "\n" 589 ); 590 591 asm volatile ( 592 ".text" "\n" 593 ".align 2" "\n" 594 ".globl " SYMBOL_STRING(ctiOpThrowNotCaught) "\n" 595 HIDE_SYMBOL(ctiOpThrowNotCaught) "\n" 596 ".thumb" "\n" 597 ".thumb_func " THUMB_FUNC_PARAM(ctiOpThrowNotCaught) "\n" 598 SYMBOL_STRING(ctiOpThrowNotCaught) ":" "\n" 599 "ldr r6, [sp, #0x2c]" "\n" 600 "ldr r5, [sp, #0x28]" "\n" 601 "ldr r4, [sp, #0x24]" "\n" 602 "ldr lr, [sp, #0x20]" "\n" 603 "add sp, sp, #0x3c" "\n" 604 "bx lr" "\n" 605 ); 606 607 #elif COMPILER(GCC) && CPU(ARM_TRADITIONAL) 608 609 asm volatile ( 610 ".text\n" 611 ".globl " SYMBOL_STRING(ctiTrampoline) "\n" 612 HIDE_SYMBOL(ctiTrampoline) "\n" 613 SYMBOL_STRING(ctiTrampoline) ":" "\n" 614 "stmdb sp!, {r1-r3}" "\n" 615 "stmdb sp!, {r4-r8, lr}" "\n" 616 "sub sp, sp, #36" "\n" 617 "mov r4, r2" "\n" 618 "mov r5, #512" "\n" 619 "mov lr, pc" "\n" 620 "mov pc, r0" "\n" 621 "add sp, sp, #36" "\n" 622 "ldmia sp!, {r4-r8, lr}" "\n" 623 "add sp, sp, #12" "\n" 624 "mov pc, lr" "\n" 625 ); 626 627 asm volatile ( 628 ".globl " SYMBOL_STRING(ctiVMThrowTrampoline) "\n" 629 HIDE_SYMBOL(ctiVMThrowTrampoline) "\n" 630 SYMBOL_STRING(ctiVMThrowTrampoline) ":" "\n" 631 "mov r0, sp" "\n" 632 "bl " SYMBOL_STRING_RELOCATION(cti_vm_throw) "\n" 633 634 // Both has the same return sequence 635 ".globl " SYMBOL_STRING(ctiOpThrowNotCaught) "\n" 636 HIDE_SYMBOL(ctiOpThrowNotCaught) "\n" 637 SYMBOL_STRING(ctiOpThrowNotCaught) ":" "\n" 638 "add sp, sp, #36" "\n" 639 "ldmia sp!, {r4-r8, lr}" "\n" 640 "add sp, sp, #12" "\n" 641 "mov pc, lr" "\n" 642 ); 643 644 #elif COMPILER(RVCT) && CPU(ARM_TRADITIONAL) 645 646 __asm EncodedJSValue ctiTrampoline(void*, RegisterFile*, CallFrame*, JSValue*, Profiler**, JSGlobalData*) 647 { 648 ARM 649 stmdb sp!, {r1-r3} 650 stmdb sp!, {r4-r8, lr} 651 sub sp, sp, #36 652 mov r4, r2 653 mov r5, #512 654 mov lr, pc 655 bx r0 656 add sp, sp, #36 657 ldmia sp!, {r4-r8, lr} 658 add sp, sp, #12 659 bx lr 660 } 661 662 __asm void ctiVMThrowTrampoline() 663 { 664 ARM 665 PRESERVE8 666 mov r0, sp 667 bl cti_vm_throw 668 add sp, sp, #36 669 ldmia sp!, {r4-r8, lr} 670 add sp, sp, #12 671 bx lr 672 } 673 674 __asm void ctiOpThrowNotCaught() 675 { 676 ARM 677 add sp, sp, #36 678 ldmia sp!, {r4-r8, lr} 679 add sp, sp, #12 680 bx lr 681 } 682 683 #elif COMPILER(MSVC) && CPU(X86) 684 685 #if USE(JIT_STUB_ARGUMENT_VA_LIST) 686 #error "JIT_STUB_ARGUMENT_VA_LIST configuration not supported on MSVC." 687 #endif 688 689 // These ASSERTs remind you that, if you change the layout of JITStackFrame, you 690 // need to change the assembly trampolines below to match. 691 COMPILE_ASSERT(offsetof(struct JITStackFrame, callFrame) == 0x38, JITStackFrame_callFrame_offset_matches_ctiTrampoline); 692 COMPILE_ASSERT(offsetof(struct JITStackFrame, code) == 0x30, JITStackFrame_code_offset_matches_ctiTrampoline); 693 COMPILE_ASSERT(offsetof(struct JITStackFrame, savedEBX) == 0x1c, JITStackFrame_stub_argument_space_matches_ctiTrampoline); 694 695 extern "C" { 696 697 __declspec(naked) EncodedJSValue ctiTrampoline(void* code, RegisterFile*, CallFrame*, JSValue* exception, Profiler**, JSGlobalData*) 698 { 699 __asm { 700 push ebp; 701 mov ebp, esp; 702 push esi; 703 push edi; 704 push ebx; 705 sub esp, 0x1c; 706 mov esi, 512; 707 mov ecx, esp; 708 mov edi, [esp + 0x38]; 709 call [esp + 0x30]; 710 add esp, 0x1c; 711 pop ebx; 712 pop edi; 713 pop esi; 714 pop ebp; 715 ret; 716 } 717 } 718 719 __declspec(naked) void ctiVMThrowTrampoline() 720 { 721 __asm { 722 mov ecx, esp; 723 call cti_vm_throw; 724 add esp, 0x1c; 725 pop ebx; 726 pop edi; 727 pop esi; 728 pop ebp; 729 ret; 730 } 731 } 732 733 __declspec(naked) void ctiOpThrowNotCaught() 734 { 735 __asm { 736 add esp, 0x1c; 737 pop ebx; 738 pop edi; 739 pop esi; 740 pop ebp; 741 ret; 742 } 743 } 744 } 745 746 #else 747 #error "JIT not supported on this platform." 748 #endif 749 750 #endif // USE(JSVALUE32_64) 751 752 #if ENABLE(OPCODE_SAMPLING) 753 #define CTI_SAMPLER stackFrame.globalData->interpreter->sampler() 754 #else 755 #define CTI_SAMPLER 0 756 #endif 757 758 JITThunks::JITThunks(JSGlobalData* globalData) 759 { 760 JIT::compileCTIMachineTrampolines(globalData, &m_executablePool, &m_trampolineStructure); 761 762 #if CPU(ARM_THUMB2) 763 // Unfortunate the arm compiler does not like the use of offsetof on JITStackFrame (since it contains non POD types), 764 // and the OBJECT_OFFSETOF macro does not appear constantish enough for it to be happy with its use in COMPILE_ASSERT 765 // macros. 766 ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, preservedReturnAddress) == 0x20); 767 ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, preservedR4) == 0x24); 768 ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, preservedR5) == 0x28); 769 ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, preservedR6) == 0x2c); 770 771 ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, registerFile) == 0x30); 772 ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, callFrame) == 0x34); 773 ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, exception) == 0x38); 774 // The fifth argument is the first item already on the stack. 775 ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, enabledProfilerReference) == 0x40); 776 777 ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, thunkReturnAddress) == 0x1C); 778 #endif 779 } 780 781 #if ENABLE(JIT_OPTIMIZE_PROPERTY_ACCESS) 782 783 NEVER_INLINE void JITThunks::tryCachePutByID(CallFrame* callFrame, CodeBlock* codeBlock, ReturnAddressPtr returnAddress, JSValue baseValue, const PutPropertySlot& slot, StructureStubInfo* stubInfo) 784 { 785 // The interpreter checks for recursion here; I do not believe this can occur in CTI. 786 787 if (!baseValue.isCell()) 788 return; 789 790 // Uncacheable: give up. 791 if (!slot.isCacheable()) { 792 ctiPatchCallByReturnAddress(codeBlock, returnAddress, FunctionPtr(cti_op_put_by_id_generic)); 793 return; 794 } 795 796 JSCell* baseCell = asCell(baseValue); 797 Structure* structure = baseCell->structure(); 798 799 if (structure->isUncacheableDictionary()) { 800 ctiPatchCallByReturnAddress(codeBlock, returnAddress, FunctionPtr(cti_op_put_by_id_generic)); 801 return; 802 } 803 804 // If baseCell != base, then baseCell must be a proxy for another object. 805 if (baseCell != slot.base()) { 806 ctiPatchCallByReturnAddress(codeBlock, returnAddress, FunctionPtr(cti_op_put_by_id_generic)); 807 return; 808 } 809 810 // Cache hit: Specialize instruction and ref Structures. 811 812 // Structure transition, cache transition info 813 if (slot.type() == PutPropertySlot::NewProperty) { 814 if (structure->isDictionary()) { 815 ctiPatchCallByReturnAddress(codeBlock, returnAddress, FunctionPtr(cti_op_put_by_id_generic)); 816 return; 817 } 818 819 // put_by_id_transition checks the prototype chain for setters. 820 normalizePrototypeChain(callFrame, baseCell); 821 822 StructureChain* prototypeChain = structure->prototypeChain(callFrame); 823 stubInfo->initPutByIdTransition(structure->previousID(), structure, prototypeChain); 824 JIT::compilePutByIdTransition(callFrame->scopeChain()->globalData, codeBlock, stubInfo, structure->previousID(), structure, slot.cachedOffset(), prototypeChain, returnAddress); 825 return; 826 } 827 828 stubInfo->initPutByIdReplace(structure); 829 830 JIT::patchPutByIdReplace(codeBlock, stubInfo, structure, slot.cachedOffset(), returnAddress); 831 } 832 833 NEVER_INLINE void JITThunks::tryCacheGetByID(CallFrame* callFrame, CodeBlock* codeBlock, ReturnAddressPtr returnAddress, JSValue baseValue, const Identifier& propertyName, const PropertySlot& slot, StructureStubInfo* stubInfo) 834 { 835 // FIXME: Write a test that proves we need to check for recursion here just 836 // like the interpreter does, then add a check for recursion. 837 838 // FIXME: Cache property access for immediates. 839 if (!baseValue.isCell()) { 840 ctiPatchCallByReturnAddress(codeBlock, returnAddress, FunctionPtr(cti_op_get_by_id_generic)); 841 return; 842 } 843 844 JSGlobalData* globalData = &callFrame->globalData(); 845 846 if (isJSArray(globalData, baseValue) && propertyName == callFrame->propertyNames().length) { 847 JIT::compilePatchGetArrayLength(callFrame->scopeChain()->globalData, codeBlock, returnAddress); 848 return; 849 } 850 851 if (isJSString(globalData, baseValue) && propertyName == callFrame->propertyNames().length) { 852 // The tradeoff of compiling an patched inline string length access routine does not seem 853 // to pay off, so we currently only do this for arrays. 854 ctiPatchCallByReturnAddress(codeBlock, returnAddress, globalData->jitStubs.ctiStringLengthTrampoline()); 855 return; 856 } 857 858 // Uncacheable: give up. 859 if (!slot.isCacheable()) { 860 ctiPatchCallByReturnAddress(codeBlock, returnAddress, FunctionPtr(cti_op_get_by_id_generic)); 861 return; 862 } 863 864 JSCell* baseCell = asCell(baseValue); 865 Structure* structure = baseCell->structure(); 866 867 if (structure->isUncacheableDictionary()) { 868 ctiPatchCallByReturnAddress(codeBlock, returnAddress, FunctionPtr(cti_op_get_by_id_generic)); 869 return; 870 } 871 872 // Cache hit: Specialize instruction and ref Structures. 873 874 if (slot.slotBase() == baseValue) { 875 // set this up, so derefStructures can do it's job. 876 stubInfo->initGetByIdSelf(structure); 877 878 JIT::patchGetByIdSelf(codeBlock, stubInfo, structure, slot.cachedOffset(), returnAddress); 879 return; 880 } 881 882 if (structure->isDictionary()) { 883 ctiPatchCallByReturnAddress(codeBlock, returnAddress, FunctionPtr(cti_op_get_by_id_generic)); 884 return; 885 } 886 887 if (slot.slotBase() == structure->prototypeForLookup(callFrame)) { 888 ASSERT(slot.slotBase().isObject()); 889 890 JSObject* slotBaseObject = asObject(slot.slotBase()); 891 size_t offset = slot.cachedOffset(); 892 893 // Since we're accessing a prototype in a loop, it's a good bet that it 894 // should not be treated as a dictionary. 895 if (slotBaseObject->structure()->isDictionary()) { 896 slotBaseObject->flattenDictionaryObject(); 897 offset = slotBaseObject->structure()->get(propertyName); 898 } 899 900 stubInfo->initGetByIdProto(structure, slotBaseObject->structure()); 901 902 ASSERT(!structure->isDictionary()); 903 ASSERT(!slotBaseObject->structure()->isDictionary()); 904 JIT::compileGetByIdProto(callFrame->scopeChain()->globalData, callFrame, codeBlock, stubInfo, structure, slotBaseObject->structure(), offset, returnAddress); 905 return; 906 } 907 908 size_t offset = slot.cachedOffset(); 909 size_t count = normalizePrototypeChain(callFrame, baseValue, slot.slotBase(), propertyName, offset); 910 if (!count) { 911 stubInfo->accessType = access_get_by_id_generic; 912 return; 913 } 914 915 StructureChain* prototypeChain = structure->prototypeChain(callFrame); 916 stubInfo->initGetByIdChain(structure, prototypeChain); 917 JIT::compileGetByIdChain(callFrame->scopeChain()->globalData, callFrame, codeBlock, stubInfo, structure, prototypeChain, count, offset, returnAddress); 918 } 919 920 #endif // ENABLE(JIT_OPTIMIZE_PROPERTY_ACCESS) 921 922 #if USE(JIT_STUB_ARGUMENT_VA_LIST) 923 #define SETUP_VA_LISTL_ARGS va_list vl_args; va_start(vl_args, args) 924 #else 925 #define SETUP_VA_LISTL_ARGS 926 #endif 927 928 #ifndef NDEBUG 929 930 extern "C" { 931 932 static void jscGeneratedNativeCode() 933 { 934 // When executing a JIT stub function (which might do an allocation), we hack the return address 935 // to pretend to be executing this function, to keep stack logging tools from blowing out 936 // memory. 937 } 938 939 } 940 941 struct StackHack { 942 ALWAYS_INLINE StackHack(JITStackFrame& stackFrame) 943 : stackFrame(stackFrame) 944 , savedReturnAddress(*stackFrame.returnAddressSlot()) 945 { 946 *stackFrame.returnAddressSlot() = ReturnAddressPtr(FunctionPtr(jscGeneratedNativeCode)); 947 } 948 949 ALWAYS_INLINE ~StackHack() 950 { 951 *stackFrame.returnAddressSlot() = savedReturnAddress; 952 } 953 954 JITStackFrame& stackFrame; 955 ReturnAddressPtr savedReturnAddress; 956 }; 957 958 #define STUB_INIT_STACK_FRAME(stackFrame) SETUP_VA_LISTL_ARGS; JITStackFrame& stackFrame = *reinterpret_cast<JITStackFrame*>(STUB_ARGS); StackHack stackHack(stackFrame) 959 #define STUB_SET_RETURN_ADDRESS(returnAddress) stackHack.savedReturnAddress = ReturnAddressPtr(returnAddress) 960 #define STUB_RETURN_ADDRESS stackHack.savedReturnAddress 961 962 #else 963 964 #define STUB_INIT_STACK_FRAME(stackFrame) SETUP_VA_LISTL_ARGS; JITStackFrame& stackFrame = *reinterpret_cast<JITStackFrame*>(STUB_ARGS) 965 #define STUB_SET_RETURN_ADDRESS(returnAddress) *stackFrame.returnAddressSlot() = ReturnAddressPtr(returnAddress) 966 #define STUB_RETURN_ADDRESS *stackFrame.returnAddressSlot() 967 968 #endif 969 970 // The reason this is not inlined is to avoid having to do a PIC branch 971 // to get the address of the ctiVMThrowTrampoline function. It's also 972 // good to keep the code size down by leaving as much of the exception 973 // handling code out of line as possible. 974 static NEVER_INLINE void returnToThrowTrampoline(JSGlobalData* globalData, ReturnAddressPtr exceptionLocation, ReturnAddressPtr& returnAddressSlot) 975 { 976 ASSERT(globalData->exception); 977 globalData->exceptionLocation = exceptionLocation; 978 returnAddressSlot = ReturnAddressPtr(FunctionPtr(ctiVMThrowTrampoline)); 979 } 980 981 static NEVER_INLINE void throwStackOverflowError(CallFrame* callFrame, JSGlobalData* globalData, ReturnAddressPtr exceptionLocation, ReturnAddressPtr& returnAddressSlot) 982 { 983 globalData->exception = createStackOverflowError(callFrame); 984 returnToThrowTrampoline(globalData, exceptionLocation, returnAddressSlot); 985 } 986 987 #define VM_THROW_EXCEPTION() \ 988 do { \ 989 VM_THROW_EXCEPTION_AT_END(); \ 990 return 0; \ 991 } while (0) 992 #define VM_THROW_EXCEPTION_AT_END() \ 993 returnToThrowTrampoline(stackFrame.globalData, STUB_RETURN_ADDRESS, STUB_RETURN_ADDRESS) 994 995 #define CHECK_FOR_EXCEPTION() \ 996 do { \ 997 if (UNLIKELY(stackFrame.globalData->exception)) \ 998 VM_THROW_EXCEPTION(); \ 999 } while (0) 1000 #define CHECK_FOR_EXCEPTION_AT_END() \ 1001 do { \ 1002 if (UNLIKELY(stackFrame.globalData->exception)) \ 1003 VM_THROW_EXCEPTION_AT_END(); \ 1004 } while (0) 1005 #define CHECK_FOR_EXCEPTION_VOID() \ 1006 do { \ 1007 if (UNLIKELY(stackFrame.globalData->exception)) { \ 1008 VM_THROW_EXCEPTION_AT_END(); \ 1009 return; \ 1010 } \ 1011 } while (0) 1012 1013 #if CPU(ARM_THUMB2) 1014 1015 #define DEFINE_STUB_FUNCTION(rtype, op) \ 1016 extern "C" { \ 1017 rtype JITStubThunked_##op(STUB_ARGS_DECLARATION); \ 1018 }; \ 1019 asm volatile ( \ 1020 ".text" "\n" \ 1021 ".align 2" "\n" \ 1022 ".globl " SYMBOL_STRING(cti_##op) "\n" \ 1023 HIDE_SYMBOL(cti_##op) "\n" \ 1024 ".thumb" "\n" \ 1025 ".thumb_func " THUMB_FUNC_PARAM(cti_##op) "\n" \ 1026 SYMBOL_STRING(cti_##op) ":" "\n" \ 1027 "str lr, [sp, #0x1c]" "\n" \ 1028 "bl " SYMBOL_STRING(JITStubThunked_##op) "\n" \ 1029 "ldr lr, [sp, #0x1c]" "\n" \ 1030 "bx lr" "\n" \ 1031 ); \ 1032 rtype JITStubThunked_##op(STUB_ARGS_DECLARATION) \ 1033 1034 #elif CPU(ARM_TRADITIONAL) && COMPILER(GCC) 1035 1036 #if USE(JSVALUE32_64) 1037 #define THUNK_RETURN_ADDRESS_OFFSET 64 1038 #else 1039 #define THUNK_RETURN_ADDRESS_OFFSET 32 1040 #endif 1041 1042 COMPILE_ASSERT(offsetof(struct JITStackFrame, thunkReturnAddress) == THUNK_RETURN_ADDRESS_OFFSET, JITStackFrame_thunkReturnAddress_offset_mismatch); 1043 1044 #define DEFINE_STUB_FUNCTION(rtype, op) \ 1045 extern "C" { \ 1046 rtype JITStubThunked_##op(STUB_ARGS_DECLARATION); \ 1047 }; \ 1048 asm volatile ( \ 1049 ".globl " SYMBOL_STRING(cti_##op) "\n" \ 1050 SYMBOL_STRING(cti_##op) ":" "\n" \ 1051 "str lr, [sp, #" STRINGIZE_VALUE_OF(THUNK_RETURN_ADDRESS_OFFSET) "]" "\n" \ 1052 "bl " SYMBOL_STRING(JITStubThunked_##op) "\n" \ 1053 "ldr lr, [sp, #" STRINGIZE_VALUE_OF(THUNK_RETURN_ADDRESS_OFFSET) "]" "\n" \ 1054 "mov pc, lr" "\n" \ 1055 ); \ 1056 rtype JITStubThunked_##op(STUB_ARGS_DECLARATION) 1057 1058 #elif CPU(ARM_TRADITIONAL) && COMPILER(RVCT) 1059 1060 #define DEFINE_STUB_FUNCTION(rtype, op) rtype JITStubThunked_##op(STUB_ARGS_DECLARATION) 1061 1062 /* The following is a workaround for RVCT toolchain; precompiler macros are not expanded before the code is passed to the assembler */ 1063 1064 /* The following section is a template to generate code for GeneratedJITStubs_RVCT.h */ 1065 /* The pattern "#xxx#" will be replaced with "xxx" */ 1066 1067 /* 1068 RVCT(extern "C" #rtype# JITStubThunked_#op#(STUB_ARGS_DECLARATION);) 1069 RVCT(__asm #rtype# cti_#op#(STUB_ARGS_DECLARATION)) 1070 RVCT({) 1071 RVCT( ARM) 1072 RVCT( IMPORT JITStubThunked_#op#) 1073 RVCT( str lr, [sp, #32]) 1074 RVCT( bl JITStubThunked_#op#) 1075 RVCT( ldr lr, [sp, #32]) 1076 RVCT( bx lr) 1077 RVCT(}) 1078 RVCT() 1079 */ 1080 1081 /* Include the generated file */ 1082 #include "GeneratedJITStubs_RVCT.h" 1083 1084 #else 1085 #define DEFINE_STUB_FUNCTION(rtype, op) rtype JIT_STUB cti_##op(STUB_ARGS_DECLARATION) 1086 #endif 1087 1088 DEFINE_STUB_FUNCTION(EncodedJSValue, op_convert_this) 1089 { 1090 STUB_INIT_STACK_FRAME(stackFrame); 1091 1092 JSValue v1 = stackFrame.args[0].jsValue(); 1093 CallFrame* callFrame = stackFrame.callFrame; 1094 1095 JSObject* result = v1.toThisObject(callFrame); 1096 CHECK_FOR_EXCEPTION_AT_END(); 1097 return JSValue::encode(result); 1098 } 1099 1100 DEFINE_STUB_FUNCTION(void, op_end) 1101 { 1102 STUB_INIT_STACK_FRAME(stackFrame); 1103 1104 ScopeChainNode* scopeChain = stackFrame.callFrame->scopeChain(); 1105 ASSERT(scopeChain->refCount > 1); 1106 scopeChain->deref(); 1107 } 1108 1109 DEFINE_STUB_FUNCTION(EncodedJSValue, op_add) 1110 { 1111 STUB_INIT_STACK_FRAME(stackFrame); 1112 1113 JSValue v1 = stackFrame.args[0].jsValue(); 1114 JSValue v2 = stackFrame.args[1].jsValue(); 1115 CallFrame* callFrame = stackFrame.callFrame; 1116 1117 if (v1.isString()) { 1118 JSValue result = v2.isString() 1119 ? jsString(callFrame, asString(v1), asString(v2)) 1120 : jsString(callFrame, asString(v1), v2.toPrimitiveString(callFrame)); 1121 CHECK_FOR_EXCEPTION_AT_END(); 1122 return JSValue::encode(result); 1123 } 1124 1125 double left = 0.0, right; 1126 if (v1.getNumber(left) && v2.getNumber(right)) 1127 return JSValue::encode(jsNumber(stackFrame.globalData, left + right)); 1128 1129 // All other cases are pretty uncommon 1130 JSValue result = jsAddSlowCase(callFrame, v1, v2); 1131 CHECK_FOR_EXCEPTION_AT_END(); 1132 return JSValue::encode(result); 1133 } 1134 1135 DEFINE_STUB_FUNCTION(EncodedJSValue, op_pre_inc) 1136 { 1137 STUB_INIT_STACK_FRAME(stackFrame); 1138 1139 JSValue v = stackFrame.args[0].jsValue(); 1140 1141 CallFrame* callFrame = stackFrame.callFrame; 1142 JSValue result = jsNumber(stackFrame.globalData, v.toNumber(callFrame) + 1); 1143 CHECK_FOR_EXCEPTION_AT_END(); 1144 return JSValue::encode(result); 1145 } 1146 1147 DEFINE_STUB_FUNCTION(int, timeout_check) 1148 { 1149 STUB_INIT_STACK_FRAME(stackFrame); 1150 1151 JSGlobalData* globalData = stackFrame.globalData; 1152 TimeoutChecker& timeoutChecker = globalData->timeoutChecker; 1153 1154 if (timeoutChecker.didTimeOut(stackFrame.callFrame)) { 1155 globalData->exception = createInterruptedExecutionException(globalData); 1156 VM_THROW_EXCEPTION_AT_END(); 1157 } 1158 1159 return timeoutChecker.ticksUntilNextCheck(); 1160 } 1161 1162 DEFINE_STUB_FUNCTION(void, register_file_check) 1163 { 1164 STUB_INIT_STACK_FRAME(stackFrame); 1165 1166 if (LIKELY(stackFrame.registerFile->grow(&stackFrame.callFrame->registers()[stackFrame.callFrame->codeBlock()->m_numCalleeRegisters]))) 1167 return; 1168 1169 // Rewind to the previous call frame because op_call already optimistically 1170 // moved the call frame forward. 1171 CallFrame* oldCallFrame = stackFrame.callFrame->callerFrame(); 1172 stackFrame.callFrame = oldCallFrame; 1173 throwStackOverflowError(oldCallFrame, stackFrame.globalData, ReturnAddressPtr(oldCallFrame->returnPC()), STUB_RETURN_ADDRESS); 1174 } 1175 1176 DEFINE_STUB_FUNCTION(int, op_loop_if_lesseq) 1177 { 1178 STUB_INIT_STACK_FRAME(stackFrame); 1179 1180 JSValue src1 = stackFrame.args[0].jsValue(); 1181 JSValue src2 = stackFrame.args[1].jsValue(); 1182 CallFrame* callFrame = stackFrame.callFrame; 1183 1184 bool result = jsLessEq(callFrame, src1, src2); 1185 CHECK_FOR_EXCEPTION_AT_END(); 1186 return result; 1187 } 1188 1189 DEFINE_STUB_FUNCTION(JSObject*, op_new_object) 1190 { 1191 STUB_INIT_STACK_FRAME(stackFrame); 1192 1193 return constructEmptyObject(stackFrame.callFrame); 1194 } 1195 1196 DEFINE_STUB_FUNCTION(void, op_put_by_id_generic) 1197 { 1198 STUB_INIT_STACK_FRAME(stackFrame); 1199 1200 PutPropertySlot slot; 1201 stackFrame.args[0].jsValue().put(stackFrame.callFrame, stackFrame.args[1].identifier(), stackFrame.args[2].jsValue(), slot); 1202 CHECK_FOR_EXCEPTION_AT_END(); 1203 } 1204 1205 DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_id_generic) 1206 { 1207 STUB_INIT_STACK_FRAME(stackFrame); 1208 1209 CallFrame* callFrame = stackFrame.callFrame; 1210 Identifier& ident = stackFrame.args[1].identifier(); 1211 1212 JSValue baseValue = stackFrame.args[0].jsValue(); 1213 PropertySlot slot(baseValue); 1214 JSValue result = baseValue.get(callFrame, ident, slot); 1215 1216 CHECK_FOR_EXCEPTION_AT_END(); 1217 return JSValue::encode(result); 1218 } 1219 1220 #if ENABLE(JIT_OPTIMIZE_PROPERTY_ACCESS) 1221 1222 DEFINE_STUB_FUNCTION(void, op_put_by_id) 1223 { 1224 STUB_INIT_STACK_FRAME(stackFrame); 1225 CallFrame* callFrame = stackFrame.callFrame; 1226 Identifier& ident = stackFrame.args[1].identifier(); 1227 1228 PutPropertySlot slot; 1229 stackFrame.args[0].jsValue().put(callFrame, ident, stackFrame.args[2].jsValue(), slot); 1230 1231 CodeBlock* codeBlock = stackFrame.callFrame->codeBlock(); 1232 StructureStubInfo* stubInfo = &codeBlock->getStubInfo(STUB_RETURN_ADDRESS); 1233 if (!stubInfo->seenOnce()) 1234 stubInfo->setSeen(); 1235 else 1236 JITThunks::tryCachePutByID(callFrame, codeBlock, STUB_RETURN_ADDRESS, stackFrame.args[0].jsValue(), slot, stubInfo); 1237 1238 CHECK_FOR_EXCEPTION_AT_END(); 1239 } 1240 1241 DEFINE_STUB_FUNCTION(void, op_put_by_id_fail) 1242 { 1243 STUB_INIT_STACK_FRAME(stackFrame); 1244 1245 CallFrame* callFrame = stackFrame.callFrame; 1246 Identifier& ident = stackFrame.args[1].identifier(); 1247 1248 PutPropertySlot slot; 1249 stackFrame.args[0].jsValue().put(callFrame, ident, stackFrame.args[2].jsValue(), slot); 1250 1251 CHECK_FOR_EXCEPTION_AT_END(); 1252 } 1253 1254 DEFINE_STUB_FUNCTION(JSObject*, op_put_by_id_transition_realloc) 1255 { 1256 STUB_INIT_STACK_FRAME(stackFrame); 1257 1258 JSValue baseValue = stackFrame.args[0].jsValue(); 1259 int32_t oldSize = stackFrame.args[3].int32(); 1260 int32_t newSize = stackFrame.args[4].int32(); 1261 1262 ASSERT(baseValue.isObject()); 1263 JSObject* base = asObject(baseValue); 1264 base->allocatePropertyStorage(oldSize, newSize); 1265 1266 return base; 1267 } 1268 1269 DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_id_method_check) 1270 { 1271 STUB_INIT_STACK_FRAME(stackFrame); 1272 1273 CallFrame* callFrame = stackFrame.callFrame; 1274 Identifier& ident = stackFrame.args[1].identifier(); 1275 1276 JSValue baseValue = stackFrame.args[0].jsValue(); 1277 PropertySlot slot(baseValue); 1278 JSValue result = baseValue.get(callFrame, ident, slot); 1279 CHECK_FOR_EXCEPTION(); 1280 1281 CodeBlock* codeBlock = stackFrame.callFrame->codeBlock(); 1282 MethodCallLinkInfo& methodCallLinkInfo = codeBlock->getMethodCallLinkInfo(STUB_RETURN_ADDRESS); 1283 1284 if (!methodCallLinkInfo.seenOnce()) { 1285 methodCallLinkInfo.setSeen(); 1286 return JSValue::encode(result); 1287 } 1288 1289 // If we successfully got something, then the base from which it is being accessed must 1290 // be an object. (Assertion to ensure asObject() call below is safe, which comes after 1291 // an isCacheable() chceck. 1292 ASSERT(!slot.isCacheable() || slot.slotBase().isObject()); 1293 1294 // Check that: 1295 // * We're dealing with a JSCell, 1296 // * the property is cachable, 1297 // * it's not a dictionary 1298 // * there is a function cached. 1299 Structure* structure; 1300 JSCell* specific; 1301 JSObject* slotBaseObject; 1302 if (baseValue.isCell() 1303 && slot.isCacheable() 1304 && !(structure = asCell(baseValue)->structure())->isUncacheableDictionary() 1305 && (slotBaseObject = asObject(slot.slotBase()))->getPropertySpecificValue(callFrame, ident, specific) 1306 && specific 1307 ) { 1308 1309 JSFunction* callee = (JSFunction*)specific; 1310 1311 // Since we're accessing a prototype in a loop, it's a good bet that it 1312 // should not be treated as a dictionary. 1313 if (slotBaseObject->structure()->isDictionary()) 1314 slotBaseObject->flattenDictionaryObject(); 1315 1316 // The result fetched should always be the callee! 1317 ASSERT(result == JSValue(callee)); 1318 1319 // Check to see if the function is on the object's prototype. Patch up the code to optimize. 1320 if (slot.slotBase() == structure->prototypeForLookup(callFrame)) { 1321 JIT::patchMethodCallProto(codeBlock, methodCallLinkInfo, callee, structure, slotBaseObject, STUB_RETURN_ADDRESS); 1322 return JSValue::encode(result); 1323 } 1324 1325 // Check to see if the function is on the object itself. 1326 // Since we generate the method-check to check both the structure and a prototype-structure (since this 1327 // is the common case) we have a problem - we need to patch the prototype structure check to do something 1328 // useful. We could try to nop it out altogether, but that's a little messy, so lets do something simpler 1329 // for now. For now it performs a check on a special object on the global object only used for this 1330 // purpose. The object is in no way exposed, and as such the check will always pass. 1331 if (slot.slotBase() == baseValue) { 1332 JIT::patchMethodCallProto(codeBlock, methodCallLinkInfo, callee, structure, callFrame->scopeChain()->globalObject->methodCallDummy(), STUB_RETURN_ADDRESS); 1333 return JSValue::encode(result); 1334 } 1335 } 1336 1337 // Revert the get_by_id op back to being a regular get_by_id - allow it to cache like normal, if it needs to. 1338 ctiPatchCallByReturnAddress(codeBlock, STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_id)); 1339 return JSValue::encode(result); 1340 } 1341 1342 DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_id) 1343 { 1344 STUB_INIT_STACK_FRAME(stackFrame); 1345 CallFrame* callFrame = stackFrame.callFrame; 1346 Identifier& ident = stackFrame.args[1].identifier(); 1347 1348 JSValue baseValue = stackFrame.args[0].jsValue(); 1349 PropertySlot slot(baseValue); 1350 JSValue result = baseValue.get(callFrame, ident, slot); 1351 1352 CodeBlock* codeBlock = stackFrame.callFrame->codeBlock(); 1353 StructureStubInfo* stubInfo = &codeBlock->getStubInfo(STUB_RETURN_ADDRESS); 1354 if (!stubInfo->seenOnce()) 1355 stubInfo->setSeen(); 1356 else 1357 JITThunks::tryCacheGetByID(callFrame, codeBlock, STUB_RETURN_ADDRESS, baseValue, ident, slot, stubInfo); 1358 1359 CHECK_FOR_EXCEPTION_AT_END(); 1360 return JSValue::encode(result); 1361 } 1362 1363 DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_id_self_fail) 1364 { 1365 STUB_INIT_STACK_FRAME(stackFrame); 1366 1367 CallFrame* callFrame = stackFrame.callFrame; 1368 Identifier& ident = stackFrame.args[1].identifier(); 1369 1370 JSValue baseValue = stackFrame.args[0].jsValue(); 1371 PropertySlot slot(baseValue); 1372 JSValue result = baseValue.get(callFrame, ident, slot); 1373 1374 CHECK_FOR_EXCEPTION(); 1375 1376 if (baseValue.isCell() 1377 && slot.isCacheable() 1378 && !asCell(baseValue)->structure()->isUncacheableDictionary() 1379 && slot.slotBase() == baseValue) { 1380 1381 CodeBlock* codeBlock = callFrame->codeBlock(); 1382 StructureStubInfo* stubInfo = &codeBlock->getStubInfo(STUB_RETURN_ADDRESS); 1383 1384 ASSERT(slot.slotBase().isObject()); 1385 1386 PolymorphicAccessStructureList* polymorphicStructureList; 1387 int listIndex = 1; 1388 1389 if (stubInfo->accessType == access_get_by_id_self) { 1390 ASSERT(!stubInfo->stubRoutine); 1391 polymorphicStructureList = new PolymorphicAccessStructureList(CodeLocationLabel(), stubInfo->u.getByIdSelf.baseObjectStructure); 1392 stubInfo->initGetByIdSelfList(polymorphicStructureList, 2); 1393 } else { 1394 polymorphicStructureList = stubInfo->u.getByIdSelfList.structureList; 1395 listIndex = stubInfo->u.getByIdSelfList.listSize; 1396 stubInfo->u.getByIdSelfList.listSize++; 1397 } 1398 1399 JIT::compileGetByIdSelfList(callFrame->scopeChain()->globalData, codeBlock, stubInfo, polymorphicStructureList, listIndex, asCell(baseValue)->structure(), slot.cachedOffset()); 1400 1401 if (listIndex == (POLYMORPHIC_LIST_CACHE_SIZE - 1)) 1402 ctiPatchCallByReturnAddress(codeBlock, STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_id_generic)); 1403 } else 1404 ctiPatchCallByReturnAddress(callFrame->codeBlock(), STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_id_generic)); 1405 return JSValue::encode(result); 1406 } 1407 1408 static PolymorphicAccessStructureList* getPolymorphicAccessStructureListSlot(StructureStubInfo* stubInfo, int& listIndex) 1409 { 1410 PolymorphicAccessStructureList* prototypeStructureList = 0; 1411 listIndex = 1; 1412 1413 switch (stubInfo->accessType) { 1414 case access_get_by_id_proto: 1415 prototypeStructureList = new PolymorphicAccessStructureList(stubInfo->stubRoutine, stubInfo->u.getByIdProto.baseObjectStructure, stubInfo->u.getByIdProto.prototypeStructure); 1416 stubInfo->stubRoutine = CodeLocationLabel(); 1417 stubInfo->initGetByIdProtoList(prototypeStructureList, 2); 1418 break; 1419 case access_get_by_id_chain: 1420 prototypeStructureList = new PolymorphicAccessStructureList(stubInfo->stubRoutine, stubInfo->u.getByIdChain.baseObjectStructure, stubInfo->u.getByIdChain.chain); 1421 stubInfo->stubRoutine = CodeLocationLabel(); 1422 stubInfo->initGetByIdProtoList(prototypeStructureList, 2); 1423 break; 1424 case access_get_by_id_proto_list: 1425 prototypeStructureList = stubInfo->u.getByIdProtoList.structureList; 1426 listIndex = stubInfo->u.getByIdProtoList.listSize; 1427 stubInfo->u.getByIdProtoList.listSize++; 1428 break; 1429 default: 1430 ASSERT_NOT_REACHED(); 1431 } 1432 1433 ASSERT(listIndex < POLYMORPHIC_LIST_CACHE_SIZE); 1434 return prototypeStructureList; 1435 } 1436 1437 DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_id_proto_list) 1438 { 1439 STUB_INIT_STACK_FRAME(stackFrame); 1440 1441 CallFrame* callFrame = stackFrame.callFrame; 1442 const Identifier& propertyName = stackFrame.args[1].identifier(); 1443 1444 JSValue baseValue = stackFrame.args[0].jsValue(); 1445 PropertySlot slot(baseValue); 1446 JSValue result = baseValue.get(callFrame, propertyName, slot); 1447 1448 CHECK_FOR_EXCEPTION(); 1449 1450 if (!baseValue.isCell() || !slot.isCacheable() || asCell(baseValue)->structure()->isDictionary()) { 1451 ctiPatchCallByReturnAddress(callFrame->codeBlock(), STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_id_proto_fail)); 1452 return JSValue::encode(result); 1453 } 1454 1455 Structure* structure = asCell(baseValue)->structure(); 1456 CodeBlock* codeBlock = callFrame->codeBlock(); 1457 StructureStubInfo* stubInfo = &codeBlock->getStubInfo(STUB_RETURN_ADDRESS); 1458 1459 ASSERT(slot.slotBase().isObject()); 1460 JSObject* slotBaseObject = asObject(slot.slotBase()); 1461 1462 size_t offset = slot.cachedOffset(); 1463 1464 if (slot.slotBase() == baseValue) 1465 ctiPatchCallByReturnAddress(codeBlock, STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_id_proto_fail)); 1466 else if (slot.slotBase() == asCell(baseValue)->structure()->prototypeForLookup(callFrame)) { 1467 ASSERT(!asCell(baseValue)->structure()->isDictionary()); 1468 // Since we're accessing a prototype in a loop, it's a good bet that it 1469 // should not be treated as a dictionary. 1470 if (slotBaseObject->structure()->isDictionary()) { 1471 slotBaseObject->flattenDictionaryObject(); 1472 offset = slotBaseObject->structure()->get(propertyName); 1473 } 1474 1475 int listIndex; 1476 PolymorphicAccessStructureList* prototypeStructureList = getPolymorphicAccessStructureListSlot(stubInfo, listIndex); 1477 1478 JIT::compileGetByIdProtoList(callFrame->scopeChain()->globalData, callFrame, codeBlock, stubInfo, prototypeStructureList, listIndex, structure, slotBaseObject->structure(), offset); 1479 1480 if (listIndex == (POLYMORPHIC_LIST_CACHE_SIZE - 1)) 1481 ctiPatchCallByReturnAddress(codeBlock, STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_id_proto_list_full)); 1482 } else if (size_t count = normalizePrototypeChain(callFrame, baseValue, slot.slotBase(), propertyName, offset)) { 1483 ASSERT(!asCell(baseValue)->structure()->isDictionary()); 1484 int listIndex; 1485 PolymorphicAccessStructureList* prototypeStructureList = getPolymorphicAccessStructureListSlot(stubInfo, listIndex); 1486 1487 StructureChain* protoChain = structure->prototypeChain(callFrame); 1488 JIT::compileGetByIdChainList(callFrame->scopeChain()->globalData, callFrame, codeBlock, stubInfo, prototypeStructureList, listIndex, structure, protoChain, count, offset); 1489 1490 if (listIndex == (POLYMORPHIC_LIST_CACHE_SIZE - 1)) 1491 ctiPatchCallByReturnAddress(codeBlock, STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_id_proto_list_full)); 1492 } else 1493 ctiPatchCallByReturnAddress(codeBlock, STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_id_proto_fail)); 1494 1495 return JSValue::encode(result); 1496 } 1497 1498 DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_id_proto_list_full) 1499 { 1500 STUB_INIT_STACK_FRAME(stackFrame); 1501 1502 JSValue baseValue = stackFrame.args[0].jsValue(); 1503 PropertySlot slot(baseValue); 1504 JSValue result = baseValue.get(stackFrame.callFrame, stackFrame.args[1].identifier(), slot); 1505 1506 CHECK_FOR_EXCEPTION_AT_END(); 1507 return JSValue::encode(result); 1508 } 1509 1510 DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_id_proto_fail) 1511 { 1512 STUB_INIT_STACK_FRAME(stackFrame); 1513 1514 JSValue baseValue = stackFrame.args[0].jsValue(); 1515 PropertySlot slot(baseValue); 1516 JSValue result = baseValue.get(stackFrame.callFrame, stackFrame.args[1].identifier(), slot); 1517 1518 CHECK_FOR_EXCEPTION_AT_END(); 1519 return JSValue::encode(result); 1520 } 1521 1522 DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_id_array_fail) 1523 { 1524 STUB_INIT_STACK_FRAME(stackFrame); 1525 1526 JSValue baseValue = stackFrame.args[0].jsValue(); 1527 PropertySlot slot(baseValue); 1528 JSValue result = baseValue.get(stackFrame.callFrame, stackFrame.args[1].identifier(), slot); 1529 1530 CHECK_FOR_EXCEPTION_AT_END(); 1531 return JSValue::encode(result); 1532 } 1533 1534 DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_id_string_fail) 1535 { 1536 STUB_INIT_STACK_FRAME(stackFrame); 1537 1538 JSValue baseValue = stackFrame.args[0].jsValue(); 1539 PropertySlot slot(baseValue); 1540 JSValue result = baseValue.get(stackFrame.callFrame, stackFrame.args[1].identifier(), slot); 1541 1542 CHECK_FOR_EXCEPTION_AT_END(); 1543 return JSValue::encode(result); 1544 } 1545 1546 #endif // ENABLE(JIT_OPTIMIZE_PROPERTY_ACCESS) 1547 1548 DEFINE_STUB_FUNCTION(EncodedJSValue, op_instanceof) 1549 { 1550 STUB_INIT_STACK_FRAME(stackFrame); 1551 1552 CallFrame* callFrame = stackFrame.callFrame; 1553 JSValue value = stackFrame.args[0].jsValue(); 1554 JSValue baseVal = stackFrame.args[1].jsValue(); 1555 JSValue proto = stackFrame.args[2].jsValue(); 1556 1557 // At least one of these checks must have failed to get to the slow case. 1558 ASSERT(!value.isCell() || !baseVal.isCell() || !proto.isCell() 1559 || !value.isObject() || !baseVal.isObject() || !proto.isObject() 1560 || (asObject(baseVal)->structure()->typeInfo().flags() & (ImplementsHasInstance | OverridesHasInstance)) != ImplementsHasInstance); 1561 1562 1563 // ECMA-262 15.3.5.3: 1564 // Throw an exception either if baseVal is not an object, or if it does not implement 'HasInstance' (i.e. is a function). 1565 TypeInfo typeInfo(UnspecifiedType); 1566 if (!baseVal.isObject() || !(typeInfo = asObject(baseVal)->structure()->typeInfo()).implementsHasInstance()) { 1567 CallFrame* callFrame = stackFrame.callFrame; 1568 CodeBlock* codeBlock = callFrame->codeBlock(); 1569 unsigned vPCIndex = codeBlock->getBytecodeIndex(callFrame, STUB_RETURN_ADDRESS); 1570 stackFrame.globalData->exception = createInvalidParamError(callFrame, "instanceof", baseVal, vPCIndex, codeBlock); 1571 VM_THROW_EXCEPTION(); 1572 } 1573 ASSERT(typeInfo.type() != UnspecifiedType); 1574 1575 if (!typeInfo.overridesHasInstance()) { 1576 if (!value.isObject()) 1577 return JSValue::encode(jsBoolean(false)); 1578 1579 if (!proto.isObject()) { 1580 throwError(callFrame, TypeError, "instanceof called on an object with an invalid prototype property."); 1581 VM_THROW_EXCEPTION(); 1582 } 1583 } 1584 1585 JSValue result = jsBoolean(asObject(baseVal)->hasInstance(callFrame, value, proto)); 1586 CHECK_FOR_EXCEPTION_AT_END(); 1587 1588 return JSValue::encode(result); 1589 } 1590 1591 DEFINE_STUB_FUNCTION(EncodedJSValue, op_del_by_id) 1592 { 1593 STUB_INIT_STACK_FRAME(stackFrame); 1594 1595 CallFrame* callFrame = stackFrame.callFrame; 1596 1597 JSObject* baseObj = stackFrame.args[0].jsValue().toObject(callFrame); 1598 1599 JSValue result = jsBoolean(baseObj->deleteProperty(callFrame, stackFrame.args[1].identifier())); 1600 CHECK_FOR_EXCEPTION_AT_END(); 1601 return JSValue::encode(result); 1602 } 1603 1604 DEFINE_STUB_FUNCTION(EncodedJSValue, op_mul) 1605 { 1606 STUB_INIT_STACK_FRAME(stackFrame); 1607 1608 JSValue src1 = stackFrame.args[0].jsValue(); 1609 JSValue src2 = stackFrame.args[1].jsValue(); 1610 1611 double left; 1612 double right; 1613 if (src1.getNumber(left) && src2.getNumber(right)) 1614 return JSValue::encode(jsNumber(stackFrame.globalData, left * right)); 1615 1616 CallFrame* callFrame = stackFrame.callFrame; 1617 JSValue result = jsNumber(stackFrame.globalData, src1.toNumber(callFrame) * src2.toNumber(callFrame)); 1618 CHECK_FOR_EXCEPTION_AT_END(); 1619 return JSValue::encode(result); 1620 } 1621 1622 DEFINE_STUB_FUNCTION(JSObject*, op_new_func) 1623 { 1624 STUB_INIT_STACK_FRAME(stackFrame); 1625 1626 return stackFrame.args[0].function()->make(stackFrame.callFrame, stackFrame.callFrame->scopeChain()); 1627 } 1628 1629 DEFINE_STUB_FUNCTION(void*, op_call_JSFunction) 1630 { 1631 STUB_INIT_STACK_FRAME(stackFrame); 1632 1633 #if !ASSERT_DISABLED 1634 CallData callData; 1635 ASSERT(stackFrame.args[0].jsValue().getCallData(callData) == CallTypeJS); 1636 #endif 1637 1638 JSFunction* function = asFunction(stackFrame.args[0].jsValue()); 1639 ASSERT(!function->isHostFunction()); 1640 FunctionExecutable* executable = function->jsExecutable(); 1641 ScopeChainNode* callDataScopeChain = function->scope().node(); 1642 executable->jitCode(stackFrame.callFrame, callDataScopeChain); 1643 1644 return function; 1645 } 1646 1647 DEFINE_STUB_FUNCTION(VoidPtrPair, op_call_arityCheck) 1648 { 1649 STUB_INIT_STACK_FRAME(stackFrame); 1650 1651 CallFrame* callFrame = stackFrame.callFrame; 1652 JSFunction* callee = asFunction(stackFrame.args[0].jsValue()); 1653 ASSERT(!callee->isHostFunction()); 1654 CodeBlock* newCodeBlock = &callee->jsExecutable()->generatedBytecode(); 1655 int argCount = stackFrame.args[2].int32(); 1656 1657 ASSERT(argCount != newCodeBlock->m_numParameters); 1658 1659 CallFrame* oldCallFrame = callFrame->callerFrame(); 1660 1661 if (argCount > newCodeBlock->m_numParameters) { 1662 size_t numParameters = newCodeBlock->m_numParameters; 1663 Register* r = callFrame->registers() + numParameters; 1664 1665 Register* argv = r - RegisterFile::CallFrameHeaderSize - numParameters - argCount; 1666 for (size_t i = 0; i < numParameters; ++i) 1667 argv[i + argCount] = argv[i]; 1668 1669 callFrame = CallFrame::create(r); 1670 callFrame->setCallerFrame(oldCallFrame); 1671 } else { 1672 size_t omittedArgCount = newCodeBlock->m_numParameters - argCount; 1673 Register* r = callFrame->registers() + omittedArgCount; 1674 Register* newEnd = r + newCodeBlock->m_numCalleeRegisters; 1675 if (!stackFrame.registerFile->grow(newEnd)) { 1676 // Rewind to the previous call frame because op_call already optimistically 1677 // moved the call frame forward. 1678 stackFrame.callFrame = oldCallFrame; 1679 throwStackOverflowError(oldCallFrame, stackFrame.globalData, stackFrame.args[1].returnAddress(), STUB_RETURN_ADDRESS); 1680 RETURN_POINTER_PAIR(0, 0); 1681 } 1682 1683 Register* argv = r - RegisterFile::CallFrameHeaderSize - omittedArgCount; 1684 for (size_t i = 0; i < omittedArgCount; ++i) 1685 argv[i] = jsUndefined(); 1686 1687 callFrame = CallFrame::create(r); 1688 callFrame->setCallerFrame(oldCallFrame); 1689 } 1690 1691 RETURN_POINTER_PAIR(callee, callFrame); 1692 } 1693 1694 #if ENABLE(JIT_OPTIMIZE_CALL) 1695 DEFINE_STUB_FUNCTION(void*, vm_lazyLinkCall) 1696 { 1697 STUB_INIT_STACK_FRAME(stackFrame); 1698 JSFunction* callee = asFunction(stackFrame.args[0].jsValue()); 1699 ExecutableBase* executable = callee->executable(); 1700 JITCode& jitCode = executable->generatedJITCode(); 1701 1702 CodeBlock* codeBlock = 0; 1703 if (!executable->isHostFunction()) 1704 codeBlock = &static_cast<FunctionExecutable*>(executable)->bytecode(stackFrame.callFrame, callee->scope().node()); 1705 CallLinkInfo* callLinkInfo = &stackFrame.callFrame->callerFrame()->codeBlock()->getCallLinkInfo(stackFrame.args[1].returnAddress()); 1706 1707 if (!callLinkInfo->seenOnce()) 1708 callLinkInfo->setSeen(); 1709 else 1710 JIT::linkCall(callee, stackFrame.callFrame->callerFrame()->codeBlock(), codeBlock, jitCode, callLinkInfo, stackFrame.args[2].int32(), stackFrame.globalData); 1711 1712 return jitCode.addressForCall().executableAddress(); 1713 } 1714 #endif // !ENABLE(JIT_OPTIMIZE_CALL) 1715 1716 DEFINE_STUB_FUNCTION(JSObject*, op_push_activation) 1717 { 1718 STUB_INIT_STACK_FRAME(stackFrame); 1719 1720 JSActivation* activation = new (stackFrame.globalData) JSActivation(stackFrame.callFrame, static_cast<FunctionExecutable*>(stackFrame.callFrame->codeBlock()->ownerExecutable())); 1721 stackFrame.callFrame->setScopeChain(stackFrame.callFrame->scopeChain()->copy()->push(activation)); 1722 return activation; 1723 } 1724 1725 DEFINE_STUB_FUNCTION(EncodedJSValue, op_call_NotJSFunction) 1726 { 1727 STUB_INIT_STACK_FRAME(stackFrame); 1728 1729 JSValue funcVal = stackFrame.args[0].jsValue(); 1730 1731 CallData callData; 1732 CallType callType = funcVal.getCallData(callData); 1733 1734 ASSERT(callType != CallTypeJS); 1735 1736 if (callType == CallTypeHost) { 1737 int registerOffset = stackFrame.args[1].int32(); 1738 int argCount = stackFrame.args[2].int32(); 1739 CallFrame* previousCallFrame = stackFrame.callFrame; 1740 CallFrame* callFrame = CallFrame::create(previousCallFrame->registers() + registerOffset); 1741 1742 callFrame->init(0, static_cast<Instruction*>((STUB_RETURN_ADDRESS).value()), previousCallFrame->scopeChain(), previousCallFrame, 0, argCount, 0); 1743 stackFrame.callFrame = callFrame; 1744 1745 Register* argv = stackFrame.callFrame->registers() - RegisterFile::CallFrameHeaderSize - argCount; 1746 ArgList argList(argv + 1, argCount - 1); 1747 1748 JSValue returnValue; 1749 { 1750 SamplingTool::HostCallRecord callRecord(CTI_SAMPLER); 1751 1752 // FIXME: All host methods should be calling toThisObject, but this is not presently the case. 1753 JSValue thisValue = argv[0].jsValue(); 1754 if (thisValue == jsNull()) 1755 thisValue = callFrame->globalThisValue(); 1756 1757 returnValue = callData.native.function(callFrame, asObject(funcVal), thisValue, argList); 1758 } 1759 stackFrame.callFrame = previousCallFrame; 1760 CHECK_FOR_EXCEPTION(); 1761 1762 return JSValue::encode(returnValue); 1763 } 1764 1765 ASSERT(callType == CallTypeNone); 1766 1767 CallFrame* callFrame = stackFrame.callFrame; 1768 CodeBlock* codeBlock = callFrame->codeBlock(); 1769 unsigned vPCIndex = codeBlock->getBytecodeIndex(callFrame, STUB_RETURN_ADDRESS); 1770 stackFrame.globalData->exception = createNotAFunctionError(stackFrame.callFrame, funcVal, vPCIndex, codeBlock); 1771 VM_THROW_EXCEPTION(); 1772 } 1773 1774 DEFINE_STUB_FUNCTION(void, op_create_arguments) 1775 { 1776 STUB_INIT_STACK_FRAME(stackFrame); 1777 1778 Arguments* arguments = new (stackFrame.globalData) Arguments(stackFrame.callFrame); 1779 stackFrame.callFrame->setCalleeArguments(arguments); 1780 stackFrame.callFrame[RegisterFile::ArgumentsRegister] = JSValue(arguments); 1781 } 1782 1783 DEFINE_STUB_FUNCTION(void, op_create_arguments_no_params) 1784 { 1785 STUB_INIT_STACK_FRAME(stackFrame); 1786 1787 Arguments* arguments = new (stackFrame.globalData) Arguments(stackFrame.callFrame, Arguments::NoParameters); 1788 stackFrame.callFrame->setCalleeArguments(arguments); 1789 stackFrame.callFrame[RegisterFile::ArgumentsRegister] = JSValue(arguments); 1790 } 1791 1792 DEFINE_STUB_FUNCTION(void, op_tear_off_activation) 1793 { 1794 STUB_INIT_STACK_FRAME(stackFrame); 1795 1796 ASSERT(stackFrame.callFrame->codeBlock()->needsFullScopeChain()); 1797 asActivation(stackFrame.args[0].jsValue())->copyRegisters(stackFrame.callFrame->optionalCalleeArguments()); 1798 } 1799 1800 DEFINE_STUB_FUNCTION(void, op_tear_off_arguments) 1801 { 1802 STUB_INIT_STACK_FRAME(stackFrame); 1803 1804 ASSERT(stackFrame.callFrame->codeBlock()->usesArguments() && !stackFrame.callFrame->codeBlock()->needsFullScopeChain()); 1805 if (stackFrame.callFrame->optionalCalleeArguments()) 1806 stackFrame.callFrame->optionalCalleeArguments()->copyRegisters(); 1807 } 1808 1809 DEFINE_STUB_FUNCTION(void, op_profile_will_call) 1810 { 1811 STUB_INIT_STACK_FRAME(stackFrame); 1812 1813 ASSERT(*stackFrame.enabledProfilerReference); 1814 (*stackFrame.enabledProfilerReference)->willExecute(stackFrame.callFrame, stackFrame.args[0].jsValue()); 1815 } 1816 1817 DEFINE_STUB_FUNCTION(void, op_profile_did_call) 1818 { 1819 STUB_INIT_STACK_FRAME(stackFrame); 1820 1821 ASSERT(*stackFrame.enabledProfilerReference); 1822 (*stackFrame.enabledProfilerReference)->didExecute(stackFrame.callFrame, stackFrame.args[0].jsValue()); 1823 } 1824 1825 DEFINE_STUB_FUNCTION(void, op_ret_scopeChain) 1826 { 1827 STUB_INIT_STACK_FRAME(stackFrame); 1828 1829 ASSERT(stackFrame.callFrame->codeBlock()->needsFullScopeChain()); 1830 stackFrame.callFrame->scopeChain()->deref(); 1831 } 1832 1833 DEFINE_STUB_FUNCTION(JSObject*, op_new_array) 1834 { 1835 STUB_INIT_STACK_FRAME(stackFrame); 1836 1837 ArgList argList(&stackFrame.callFrame->registers()[stackFrame.args[0].int32()], stackFrame.args[1].int32()); 1838 return constructArray(stackFrame.callFrame, argList); 1839 } 1840 1841 DEFINE_STUB_FUNCTION(EncodedJSValue, op_resolve) 1842 { 1843 STUB_INIT_STACK_FRAME(stackFrame); 1844 1845 CallFrame* callFrame = stackFrame.callFrame; 1846 ScopeChainNode* scopeChain = callFrame->scopeChain(); 1847 1848 ScopeChainIterator iter = scopeChain->begin(); 1849 ScopeChainIterator end = scopeChain->end(); 1850 ASSERT(iter != end); 1851 1852 Identifier& ident = stackFrame.args[0].identifier(); 1853 do { 1854 JSObject* o = *iter; 1855 PropertySlot slot(o); 1856 if (o->getPropertySlot(callFrame, ident, slot)) { 1857 JSValue result = slot.getValue(callFrame, ident); 1858 CHECK_FOR_EXCEPTION_AT_END(); 1859 return JSValue::encode(result); 1860 } 1861 } while (++iter != end); 1862 1863 CodeBlock* codeBlock = callFrame->codeBlock(); 1864 unsigned vPCIndex = codeBlock->getBytecodeIndex(callFrame, STUB_RETURN_ADDRESS); 1865 stackFrame.globalData->exception = createUndefinedVariableError(callFrame, ident, vPCIndex, codeBlock); 1866 VM_THROW_EXCEPTION(); 1867 } 1868 1869 DEFINE_STUB_FUNCTION(JSObject*, op_construct_JSConstruct) 1870 { 1871 STUB_INIT_STACK_FRAME(stackFrame); 1872 1873 JSFunction* constructor = asFunction(stackFrame.args[0].jsValue()); 1874 if (constructor->isHostFunction()) { 1875 CallFrame* callFrame = stackFrame.callFrame; 1876 CodeBlock* codeBlock = callFrame->codeBlock(); 1877 unsigned vPCIndex = codeBlock->getBytecodeIndex(callFrame, STUB_RETURN_ADDRESS); 1878 stackFrame.globalData->exception = createNotAConstructorError(callFrame, constructor, vPCIndex, codeBlock); 1879 VM_THROW_EXCEPTION(); 1880 } 1881 1882 #if !ASSERT_DISABLED 1883 ConstructData constructData; 1884 ASSERT(constructor->getConstructData(constructData) == ConstructTypeJS); 1885 #endif 1886 1887 Structure* structure; 1888 if (stackFrame.args[3].jsValue().isObject()) 1889 structure = asObject(stackFrame.args[3].jsValue())->inheritorID(); 1890 else 1891 structure = constructor->scope().node()->globalObject->emptyObjectStructure(); 1892 return new (stackFrame.globalData) JSObject(structure); 1893 } 1894 1895 DEFINE_STUB_FUNCTION(EncodedJSValue, op_construct_NotJSConstruct) 1896 { 1897 STUB_INIT_STACK_FRAME(stackFrame); 1898 1899 CallFrame* callFrame = stackFrame.callFrame; 1900 1901 JSValue constrVal = stackFrame.args[0].jsValue(); 1902 int argCount = stackFrame.args[2].int32(); 1903 int thisRegister = stackFrame.args[4].int32(); 1904 1905 ConstructData constructData; 1906 ConstructType constructType = constrVal.getConstructData(constructData); 1907 1908 if (constructType == ConstructTypeHost) { 1909 ArgList argList(callFrame->registers() + thisRegister + 1, argCount - 1); 1910 1911 JSValue returnValue; 1912 { 1913 SamplingTool::HostCallRecord callRecord(CTI_SAMPLER); 1914 returnValue = constructData.native.function(callFrame, asObject(constrVal), argList); 1915 } 1916 CHECK_FOR_EXCEPTION(); 1917 1918 return JSValue::encode(returnValue); 1919 } 1920 1921 ASSERT(constructType == ConstructTypeNone); 1922 1923 CodeBlock* codeBlock = callFrame->codeBlock(); 1924 unsigned vPCIndex = codeBlock->getBytecodeIndex(callFrame, STUB_RETURN_ADDRESS); 1925 stackFrame.globalData->exception = createNotAConstructorError(callFrame, constrVal, vPCIndex, codeBlock); 1926 VM_THROW_EXCEPTION(); 1927 } 1928 1929 DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_val) 1930 { 1931 STUB_INIT_STACK_FRAME(stackFrame); 1932 1933 CallFrame* callFrame = stackFrame.callFrame; 1934 JSGlobalData* globalData = stackFrame.globalData; 1935 1936 JSValue baseValue = stackFrame.args[0].jsValue(); 1937 JSValue subscript = stackFrame.args[1].jsValue(); 1938 1939 JSValue result; 1940 1941 if (LIKELY(subscript.isUInt32())) { 1942 uint32_t i = subscript.asUInt32(); 1943 if (isJSArray(globalData, baseValue)) { 1944 JSArray* jsArray = asArray(baseValue); 1945 if (jsArray->canGetIndex(i)) 1946 result = jsArray->getIndex(i); 1947 else 1948 result = jsArray->JSArray::get(callFrame, i); 1949 } else if (isJSString(globalData, baseValue) && asString(baseValue)->canGetIndex(i)) { 1950 // All fast byte array accesses are safe from exceptions so return immediately to avoid exception checks. 1951 ctiPatchCallByReturnAddress(callFrame->codeBlock(), STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_val_string)); 1952 result = asString(baseValue)->getIndex(callFrame, i); 1953 } else if (isJSByteArray(globalData, baseValue) && asByteArray(baseValue)->canAccessIndex(i)) { 1954 // All fast byte array accesses are safe from exceptions so return immediately to avoid exception checks. 1955 ctiPatchCallByReturnAddress(callFrame->codeBlock(), STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_val_byte_array)); 1956 return JSValue::encode(asByteArray(baseValue)->getIndex(callFrame, i)); 1957 } else 1958 result = baseValue.get(callFrame, i); 1959 } else { 1960 Identifier property(callFrame, subscript.toString(callFrame)); 1961 result = baseValue.get(callFrame, property); 1962 } 1963 1964 CHECK_FOR_EXCEPTION_AT_END(); 1965 return JSValue::encode(result); 1966 } 1967 1968 DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_val_string) 1969 { 1970 STUB_INIT_STACK_FRAME(stackFrame); 1971 1972 CallFrame* callFrame = stackFrame.callFrame; 1973 JSGlobalData* globalData = stackFrame.globalData; 1974 1975 JSValue baseValue = stackFrame.args[0].jsValue(); 1976 JSValue subscript = stackFrame.args[1].jsValue(); 1977 1978 JSValue result; 1979 1980 if (LIKELY(subscript.isUInt32())) { 1981 uint32_t i = subscript.asUInt32(); 1982 if (isJSString(globalData, baseValue) && asString(baseValue)->canGetIndex(i)) 1983 result = asString(baseValue)->getIndex(callFrame, i); 1984 else { 1985 result = baseValue.get(callFrame, i); 1986 if (!isJSString(globalData, baseValue)) 1987 ctiPatchCallByReturnAddress(callFrame->codeBlock(), STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_val)); 1988 } 1989 } else { 1990 Identifier property(callFrame, subscript.toString(callFrame)); 1991 result = baseValue.get(callFrame, property); 1992 } 1993 1994 CHECK_FOR_EXCEPTION_AT_END(); 1995 return JSValue::encode(result); 1996 } 1997 1998 DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_val_byte_array) 1999 { 2000 STUB_INIT_STACK_FRAME(stackFrame); 2001 2002 CallFrame* callFrame = stackFrame.callFrame; 2003 JSGlobalData* globalData = stackFrame.globalData; 2004 2005 JSValue baseValue = stackFrame.args[0].jsValue(); 2006 JSValue subscript = stackFrame.args[1].jsValue(); 2007 2008 JSValue result; 2009 2010 if (LIKELY(subscript.isUInt32())) { 2011 uint32_t i = subscript.asUInt32(); 2012 if (isJSByteArray(globalData, baseValue) && asByteArray(baseValue)->canAccessIndex(i)) { 2013 // All fast byte array accesses are safe from exceptions so return immediately to avoid exception checks. 2014 return JSValue::encode(asByteArray(baseValue)->getIndex(callFrame, i)); 2015 } 2016 2017 result = baseValue.get(callFrame, i); 2018 if (!isJSByteArray(globalData, baseValue)) 2019 ctiPatchCallByReturnAddress(callFrame->codeBlock(), STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_val)); 2020 } else { 2021 Identifier property(callFrame, subscript.toString(callFrame)); 2022 result = baseValue.get(callFrame, property); 2023 } 2024 2025 CHECK_FOR_EXCEPTION_AT_END(); 2026 return JSValue::encode(result); 2027 } 2028 2029 DEFINE_STUB_FUNCTION(EncodedJSValue, op_sub) 2030 { 2031 STUB_INIT_STACK_FRAME(stackFrame); 2032 2033 JSValue src1 = stackFrame.args[0].jsValue(); 2034 JSValue src2 = stackFrame.args[1].jsValue(); 2035 2036 double left; 2037 double right; 2038 if (src1.getNumber(left) && src2.getNumber(right)) 2039 return JSValue::encode(jsNumber(stackFrame.globalData, left - right)); 2040 2041 CallFrame* callFrame = stackFrame.callFrame; 2042 JSValue result = jsNumber(stackFrame.globalData, src1.toNumber(callFrame) - src2.toNumber(callFrame)); 2043 CHECK_FOR_EXCEPTION_AT_END(); 2044 return JSValue::encode(result); 2045 } 2046 2047 DEFINE_STUB_FUNCTION(void, op_put_by_val) 2048 { 2049 STUB_INIT_STACK_FRAME(stackFrame); 2050 2051 CallFrame* callFrame = stackFrame.callFrame; 2052 JSGlobalData* globalData = stackFrame.globalData; 2053 2054 JSValue baseValue = stackFrame.args[0].jsValue(); 2055 JSValue subscript = stackFrame.args[1].jsValue(); 2056 JSValue value = stackFrame.args[2].jsValue(); 2057 2058 if (LIKELY(subscript.isUInt32())) { 2059 uint32_t i = subscript.asUInt32(); 2060 if (isJSArray(globalData, baseValue)) { 2061 JSArray* jsArray = asArray(baseValue); 2062 if (jsArray->canSetIndex(i)) 2063 jsArray->setIndex(i, value); 2064 else 2065 jsArray->JSArray::put(callFrame, i, value); 2066 } else if (isJSByteArray(globalData, baseValue) && asByteArray(baseValue)->canAccessIndex(i)) { 2067 JSByteArray* jsByteArray = asByteArray(baseValue); 2068 ctiPatchCallByReturnAddress(callFrame->codeBlock(), STUB_RETURN_ADDRESS, FunctionPtr(cti_op_put_by_val_byte_array)); 2069 // All fast byte array accesses are safe from exceptions so return immediately to avoid exception checks. 2070 if (value.isInt32()) { 2071 jsByteArray->setIndex(i, value.asInt32()); 2072 return; 2073 } else { 2074 double dValue = 0; 2075 if (value.getNumber(dValue)) { 2076 jsByteArray->setIndex(i, dValue); 2077 return; 2078 } 2079 } 2080 2081 baseValue.put(callFrame, i, value); 2082 } else 2083 baseValue.put(callFrame, i, value); 2084 } else { 2085 Identifier property(callFrame, subscript.toString(callFrame)); 2086 if (!stackFrame.globalData->exception) { // Don't put to an object if toString threw an exception. 2087 PutPropertySlot slot; 2088 baseValue.put(callFrame, property, value, slot); 2089 } 2090 } 2091 2092 CHECK_FOR_EXCEPTION_AT_END(); 2093 } 2094 2095 DEFINE_STUB_FUNCTION(void, op_put_by_val_byte_array) 2096 { 2097 STUB_INIT_STACK_FRAME(stackFrame); 2098 2099 CallFrame* callFrame = stackFrame.callFrame; 2100 JSGlobalData* globalData = stackFrame.globalData; 2101 2102 JSValue baseValue = stackFrame.args[0].jsValue(); 2103 JSValue subscript = stackFrame.args[1].jsValue(); 2104 JSValue value = stackFrame.args[2].jsValue(); 2105 2106 if (LIKELY(subscript.isUInt32())) { 2107 uint32_t i = subscript.asUInt32(); 2108 if (isJSByteArray(globalData, baseValue) && asByteArray(baseValue)->canAccessIndex(i)) { 2109 JSByteArray* jsByteArray = asByteArray(baseValue); 2110 2111 // All fast byte array accesses are safe from exceptions so return immediately to avoid exception checks. 2112 if (value.isInt32()) { 2113 jsByteArray->setIndex(i, value.asInt32()); 2114 return; 2115 } else { 2116 double dValue = 0; 2117 if (value.getNumber(dValue)) { 2118 jsByteArray->setIndex(i, dValue); 2119 return; 2120 } 2121 } 2122 } 2123 2124 if (!isJSByteArray(globalData, baseValue)) 2125 ctiPatchCallByReturnAddress(callFrame->codeBlock(), STUB_RETURN_ADDRESS, FunctionPtr(cti_op_put_by_val)); 2126 baseValue.put(callFrame, i, value); 2127 } else { 2128 Identifier property(callFrame, subscript.toString(callFrame)); 2129 if (!stackFrame.globalData->exception) { // Don't put to an object if toString threw an exception. 2130 PutPropertySlot slot; 2131 baseValue.put(callFrame, property, value, slot); 2132 } 2133 } 2134 2135 CHECK_FOR_EXCEPTION_AT_END(); 2136 } 2137 2138 DEFINE_STUB_FUNCTION(EncodedJSValue, op_lesseq) 2139 { 2140 STUB_INIT_STACK_FRAME(stackFrame); 2141 2142 CallFrame* callFrame = stackFrame.callFrame; 2143 JSValue result = jsBoolean(jsLessEq(callFrame, stackFrame.args[0].jsValue(), stackFrame.args[1].jsValue())); 2144 CHECK_FOR_EXCEPTION_AT_END(); 2145 return JSValue::encode(result); 2146 } 2147 2148 DEFINE_STUB_FUNCTION(int, op_load_varargs) 2149 { 2150 STUB_INIT_STACK_FRAME(stackFrame); 2151 2152 CallFrame* callFrame = stackFrame.callFrame; 2153 RegisterFile* registerFile = stackFrame.registerFile; 2154 int argsOffset = stackFrame.args[0].int32(); 2155 JSValue arguments = callFrame->registers()[argsOffset].jsValue(); 2156 uint32_t argCount = 0; 2157 if (!arguments) { 2158 int providedParams = callFrame->registers()[RegisterFile::ArgumentCount].i() - 1; 2159 argCount = providedParams; 2160 int32_t sizeDelta = argsOffset + argCount + RegisterFile::CallFrameHeaderSize; 2161 Register* newEnd = callFrame->registers() + sizeDelta; 2162 if (!registerFile->grow(newEnd) || ((newEnd - callFrame->registers()) != sizeDelta)) { 2163 stackFrame.globalData->exception = createStackOverflowError(callFrame); 2164 VM_THROW_EXCEPTION(); 2165 } 2166 int32_t expectedParams = callFrame->callee()->jsExecutable()->parameterCount(); 2167 int32_t inplaceArgs = min(providedParams, expectedParams); 2168 2169 Register* inplaceArgsDst = callFrame->registers() + argsOffset; 2170 2171 Register* inplaceArgsEnd = inplaceArgsDst + inplaceArgs; 2172 Register* inplaceArgsEnd2 = inplaceArgsDst + providedParams; 2173 2174 Register* inplaceArgsSrc = callFrame->registers() - RegisterFile::CallFrameHeaderSize - expectedParams; 2175 Register* inplaceArgsSrc2 = inplaceArgsSrc - providedParams - 1 + inplaceArgs; 2176 2177 // First step is to copy the "expected" parameters from their normal location relative to the callframe 2178 while (inplaceArgsDst < inplaceArgsEnd) 2179 *inplaceArgsDst++ = *inplaceArgsSrc++; 2180 2181 // Then we copy any additional arguments that may be further up the stack ('-1' to account for 'this') 2182 while (inplaceArgsDst < inplaceArgsEnd2) 2183 *inplaceArgsDst++ = *inplaceArgsSrc2++; 2184 2185 } else if (!arguments.isUndefinedOrNull()) { 2186 if (!arguments.isObject()) { 2187 CodeBlock* codeBlock = callFrame->codeBlock(); 2188 unsigned vPCIndex = codeBlock->getBytecodeIndex(callFrame, STUB_RETURN_ADDRESS); 2189 stackFrame.globalData->exception = createInvalidParamError(callFrame, "Function.prototype.apply", arguments, vPCIndex, codeBlock); 2190 VM_THROW_EXCEPTION(); 2191 } 2192 if (asObject(arguments)->classInfo() == &Arguments::info) { 2193 Arguments* argsObject = asArguments(arguments); 2194 argCount = argsObject->numProvidedArguments(callFrame); 2195 int32_t sizeDelta = argsOffset + argCount + RegisterFile::CallFrameHeaderSize; 2196 Register* newEnd = callFrame->registers() + sizeDelta; 2197 if (!registerFile->grow(newEnd) || ((newEnd - callFrame->registers()) != sizeDelta)) { 2198 stackFrame.globalData->exception = createStackOverflowError(callFrame); 2199 VM_THROW_EXCEPTION(); 2200 } 2201 argsObject->copyToRegisters(callFrame, callFrame->registers() + argsOffset, argCount); 2202 } else if (isJSArray(&callFrame->globalData(), arguments)) { 2203 JSArray* array = asArray(arguments); 2204 argCount = array->length(); 2205 int32_t sizeDelta = argsOffset + argCount + RegisterFile::CallFrameHeaderSize; 2206 Register* newEnd = callFrame->registers() + sizeDelta; 2207 if (!registerFile->grow(newEnd) || ((newEnd - callFrame->registers()) != sizeDelta)) { 2208 stackFrame.globalData->exception = createStackOverflowError(callFrame); 2209 VM_THROW_EXCEPTION(); 2210 } 2211 array->copyToRegisters(callFrame, callFrame->registers() + argsOffset, argCount); 2212 } else if (asObject(arguments)->inherits(&JSArray::info)) { 2213 JSObject* argObject = asObject(arguments); 2214 argCount = argObject->get(callFrame, callFrame->propertyNames().length).toUInt32(callFrame); 2215 int32_t sizeDelta = argsOffset + argCount + RegisterFile::CallFrameHeaderSize; 2216 Register* newEnd = callFrame->registers() + sizeDelta; 2217 if (!registerFile->grow(newEnd) || ((newEnd - callFrame->registers()) != sizeDelta)) { 2218 stackFrame.globalData->exception = createStackOverflowError(callFrame); 2219 VM_THROW_EXCEPTION(); 2220 } 2221 Register* argsBuffer = callFrame->registers() + argsOffset; 2222 for (unsigned i = 0; i < argCount; ++i) { 2223 argsBuffer[i] = asObject(arguments)->get(callFrame, i); 2224 CHECK_FOR_EXCEPTION(); 2225 } 2226 } else { 2227 CodeBlock* codeBlock = callFrame->codeBlock(); 2228 unsigned vPCIndex = codeBlock->getBytecodeIndex(callFrame, STUB_RETURN_ADDRESS); 2229 stackFrame.globalData->exception = createInvalidParamError(callFrame, "Function.prototype.apply", arguments, vPCIndex, codeBlock); 2230 VM_THROW_EXCEPTION(); 2231 } 2232 } 2233 2234 return argCount + 1; 2235 } 2236 2237 DEFINE_STUB_FUNCTION(EncodedJSValue, op_negate) 2238 { 2239 STUB_INIT_STACK_FRAME(stackFrame); 2240 2241 JSValue src = stackFrame.args[0].jsValue(); 2242 2243 double v; 2244 if (src.getNumber(v)) 2245 return JSValue::encode(jsNumber(stackFrame.globalData, -v)); 2246 2247 CallFrame* callFrame = stackFrame.callFrame; 2248 JSValue result = jsNumber(stackFrame.globalData, -src.toNumber(callFrame)); 2249 CHECK_FOR_EXCEPTION_AT_END(); 2250 return JSValue::encode(result); 2251 } 2252 2253 DEFINE_STUB_FUNCTION(EncodedJSValue, op_resolve_base) 2254 { 2255 STUB_INIT_STACK_FRAME(stackFrame); 2256 2257 return JSValue::encode(JSC::resolveBase(stackFrame.callFrame, stackFrame.args[0].identifier(), stackFrame.callFrame->scopeChain())); 2258 } 2259 2260 DEFINE_STUB_FUNCTION(EncodedJSValue, op_resolve_skip) 2261 { 2262 STUB_INIT_STACK_FRAME(stackFrame); 2263 2264 CallFrame* callFrame = stackFrame.callFrame; 2265 ScopeChainNode* scopeChain = callFrame->scopeChain(); 2266 2267 int skip = stackFrame.args[1].int32(); 2268 2269 ScopeChainIterator iter = scopeChain->begin(); 2270 ScopeChainIterator end = scopeChain->end(); 2271 ASSERT(iter != end); 2272 while (skip--) { 2273 ++iter; 2274 ASSERT(iter != end); 2275 } 2276 Identifier& ident = stackFrame.args[0].identifier(); 2277 do { 2278 JSObject* o = *iter; 2279 PropertySlot slot(o); 2280 if (o->getPropertySlot(callFrame, ident, slot)) { 2281 JSValue result = slot.getValue(callFrame, ident); 2282 CHECK_FOR_EXCEPTION_AT_END(); 2283 return JSValue::encode(result); 2284 } 2285 } while (++iter != end); 2286 2287 CodeBlock* codeBlock = callFrame->codeBlock(); 2288 unsigned vPCIndex = codeBlock->getBytecodeIndex(callFrame, STUB_RETURN_ADDRESS); 2289 stackFrame.globalData->exception = createUndefinedVariableError(callFrame, ident, vPCIndex, codeBlock); 2290 VM_THROW_EXCEPTION(); 2291 } 2292 2293 DEFINE_STUB_FUNCTION(EncodedJSValue, op_resolve_global) 2294 { 2295 STUB_INIT_STACK_FRAME(stackFrame); 2296 2297 CallFrame* callFrame = stackFrame.callFrame; 2298 JSGlobalObject* globalObject = stackFrame.args[0].globalObject(); 2299 Identifier& ident = stackFrame.args[1].identifier(); 2300 unsigned globalResolveInfoIndex = stackFrame.args[2].int32(); 2301 ASSERT(globalObject->isGlobalObject()); 2302 2303 PropertySlot slot(globalObject); 2304 if (globalObject->getPropertySlot(callFrame, ident, slot)) { 2305 JSValue result = slot.getValue(callFrame, ident); 2306 if (slot.isCacheable() && !globalObject->structure()->isUncacheableDictionary() && slot.slotBase() == globalObject) { 2307 GlobalResolveInfo& globalResolveInfo = callFrame->codeBlock()->globalResolveInfo(globalResolveInfoIndex); 2308 if (globalResolveInfo.structure) 2309 globalResolveInfo.structure->deref(); 2310 globalObject->structure()->ref(); 2311 globalResolveInfo.structure = globalObject->structure(); 2312 globalResolveInfo.offset = slot.cachedOffset(); 2313 return JSValue::encode(result); 2314 } 2315 2316 CHECK_FOR_EXCEPTION_AT_END(); 2317 return JSValue::encode(result); 2318 } 2319 2320 unsigned vPCIndex = callFrame->codeBlock()->getBytecodeIndex(callFrame, STUB_RETURN_ADDRESS); 2321 stackFrame.globalData->exception = createUndefinedVariableError(callFrame, ident, vPCIndex, callFrame->codeBlock()); 2322 VM_THROW_EXCEPTION(); 2323 } 2324 2325 DEFINE_STUB_FUNCTION(EncodedJSValue, op_div) 2326 { 2327 STUB_INIT_STACK_FRAME(stackFrame); 2328 2329 JSValue src1 = stackFrame.args[0].jsValue(); 2330 JSValue src2 = stackFrame.args[1].jsValue(); 2331 2332 double left; 2333 double right; 2334 if (src1.getNumber(left) && src2.getNumber(right)) 2335 return JSValue::encode(jsNumber(stackFrame.globalData, left / right)); 2336 2337 CallFrame* callFrame = stackFrame.callFrame; 2338 JSValue result = jsNumber(stackFrame.globalData, src1.toNumber(callFrame) / src2.toNumber(callFrame)); 2339 CHECK_FOR_EXCEPTION_AT_END(); 2340 return JSValue::encode(result); 2341 } 2342 2343 DEFINE_STUB_FUNCTION(EncodedJSValue, op_pre_dec) 2344 { 2345 STUB_INIT_STACK_FRAME(stackFrame); 2346 2347 JSValue v = stackFrame.args[0].jsValue(); 2348 2349 CallFrame* callFrame = stackFrame.callFrame; 2350 JSValue result = jsNumber(stackFrame.globalData, v.toNumber(callFrame) - 1); 2351 CHECK_FOR_EXCEPTION_AT_END(); 2352 return JSValue::encode(result); 2353 } 2354 2355 DEFINE_STUB_FUNCTION(int, op_jless) 2356 { 2357 STUB_INIT_STACK_FRAME(stackFrame); 2358 2359 JSValue src1 = stackFrame.args[0].jsValue(); 2360 JSValue src2 = stackFrame.args[1].jsValue(); 2361 CallFrame* callFrame = stackFrame.callFrame; 2362 2363 bool result = jsLess(callFrame, src1, src2); 2364 CHECK_FOR_EXCEPTION_AT_END(); 2365 return result; 2366 } 2367 2368 DEFINE_STUB_FUNCTION(int, op_jlesseq) 2369 { 2370 STUB_INIT_STACK_FRAME(stackFrame); 2371 2372 JSValue src1 = stackFrame.args[0].jsValue(); 2373 JSValue src2 = stackFrame.args[1].jsValue(); 2374 CallFrame* callFrame = stackFrame.callFrame; 2375 2376 bool result = jsLessEq(callFrame, src1, src2); 2377 CHECK_FOR_EXCEPTION_AT_END(); 2378 return result; 2379 } 2380 2381 DEFINE_STUB_FUNCTION(EncodedJSValue, op_not) 2382 { 2383 STUB_INIT_STACK_FRAME(stackFrame); 2384 2385 JSValue src = stackFrame.args[0].jsValue(); 2386 2387 CallFrame* callFrame = stackFrame.callFrame; 2388 2389 JSValue result = jsBoolean(!src.toBoolean(callFrame)); 2390 CHECK_FOR_EXCEPTION_AT_END(); 2391 return JSValue::encode(result); 2392 } 2393 2394 DEFINE_STUB_FUNCTION(int, op_jtrue) 2395 { 2396 STUB_INIT_STACK_FRAME(stackFrame); 2397 2398 JSValue src1 = stackFrame.args[0].jsValue(); 2399 2400 CallFrame* callFrame = stackFrame.callFrame; 2401 2402 bool result = src1.toBoolean(callFrame); 2403 CHECK_FOR_EXCEPTION_AT_END(); 2404 return result; 2405 } 2406 2407 DEFINE_STUB_FUNCTION(EncodedJSValue, op_post_inc) 2408 { 2409 STUB_INIT_STACK_FRAME(stackFrame); 2410 2411 JSValue v = stackFrame.args[0].jsValue(); 2412 2413 CallFrame* callFrame = stackFrame.callFrame; 2414 2415 JSValue number = v.toJSNumber(callFrame); 2416 CHECK_FOR_EXCEPTION_AT_END(); 2417 2418 callFrame->registers()[stackFrame.args[1].int32()] = jsNumber(stackFrame.globalData, number.uncheckedGetNumber() + 1); 2419 return JSValue::encode(number); 2420 } 2421 2422 DEFINE_STUB_FUNCTION(int, op_eq) 2423 { 2424 STUB_INIT_STACK_FRAME(stackFrame); 2425 2426 JSValue src1 = stackFrame.args[0].jsValue(); 2427 JSValue src2 = stackFrame.args[1].jsValue(); 2428 2429 #if USE(JSVALUE32_64) 2430 start: 2431 if (src2.isUndefined()) { 2432 return src1.isNull() || 2433 (src1.isCell() && asCell(src1)->structure()->typeInfo().masqueradesAsUndefined()) || 2434 src1.isUndefined(); 2435 } 2436 2437 if (src2.isNull()) { 2438 return src1.isUndefined() || 2439 (src1.isCell() && asCell(src1)->structure()->typeInfo().masqueradesAsUndefined()) || 2440 src1.isNull(); 2441 } 2442 2443 if (src1.isInt32()) { 2444 if (src2.isDouble()) 2445 return src1.asInt32() == src2.asDouble(); 2446 double d = src2.toNumber(stackFrame.callFrame); 2447 CHECK_FOR_EXCEPTION(); 2448 return src1.asInt32() == d; 2449 } 2450 2451 if (src1.isDouble()) { 2452 if (src2.isInt32()) 2453 return src1.asDouble() == src2.asInt32(); 2454 double d = src2.toNumber(stackFrame.callFrame); 2455 CHECK_FOR_EXCEPTION(); 2456 return src1.asDouble() == d; 2457 } 2458 2459 if (src1.isTrue()) { 2460 if (src2.isFalse()) 2461 return false; 2462 double d = src2.toNumber(stackFrame.callFrame); 2463 CHECK_FOR_EXCEPTION(); 2464 return d == 1.0; 2465 } 2466 2467 if (src1.isFalse()) { 2468 if (src2.isTrue()) 2469 return false; 2470 double d = src2.toNumber(stackFrame.callFrame); 2471 CHECK_FOR_EXCEPTION(); 2472 return d == 0.0; 2473 } 2474 2475 if (src1.isUndefined()) 2476 return src2.isCell() && asCell(src2)->structure()->typeInfo().masqueradesAsUndefined(); 2477 2478 if (src1.isNull()) 2479 return src2.isCell() && asCell(src2)->structure()->typeInfo().masqueradesAsUndefined(); 2480 2481 JSCell* cell1 = asCell(src1); 2482 2483 if (cell1->isString()) { 2484 if (src2.isInt32()) 2485 return static_cast<JSString*>(cell1)->value(stackFrame.callFrame).toDouble() == src2.asInt32(); 2486 2487 if (src2.isDouble()) 2488 return static_cast<JSString*>(cell1)->value(stackFrame.callFrame).toDouble() == src2.asDouble(); 2489 2490 if (src2.isTrue()) 2491 return static_cast<JSString*>(cell1)->value(stackFrame.callFrame).toDouble() == 1.0; 2492 2493 if (src2.isFalse()) 2494 return static_cast<JSString*>(cell1)->value(stackFrame.callFrame).toDouble() == 0.0; 2495 2496 JSCell* cell2 = asCell(src2); 2497 if (cell2->isString()) 2498 return static_cast<JSString*>(cell1)->value(stackFrame.callFrame) == static_cast<JSString*>(cell2)->value(stackFrame.callFrame); 2499 2500 src2 = asObject(cell2)->toPrimitive(stackFrame.callFrame); 2501 CHECK_FOR_EXCEPTION(); 2502 goto start; 2503 } 2504 2505 if (src2.isObject()) 2506 return asObject(cell1) == asObject(src2); 2507 src1 = asObject(cell1)->toPrimitive(stackFrame.callFrame); 2508 CHECK_FOR_EXCEPTION(); 2509 goto start; 2510 2511 #else // USE(JSVALUE32_64) 2512 CallFrame* callFrame = stackFrame.callFrame; 2513 2514 bool result = JSValue::equalSlowCaseInline(callFrame, src1, src2); 2515 CHECK_FOR_EXCEPTION_AT_END(); 2516 return result; 2517 #endif // USE(JSVALUE32_64) 2518 } 2519 2520 #if USE(JSVALUE32_64) 2521 2522 DEFINE_STUB_FUNCTION(int, op_eq_strings) 2523 { 2524 STUB_INIT_STACK_FRAME(stackFrame); 2525 2526 JSString* string1 = stackFrame.args[0].jsString(); 2527 JSString* string2 = stackFrame.args[1].jsString(); 2528 2529 ASSERT(string1->isString()); 2530 ASSERT(string2->isString()); 2531 return string1->value(stackFrame.callFrame) == string2->value(stackFrame.callFrame); 2532 } 2533 2534 #endif 2535 2536 DEFINE_STUB_FUNCTION(EncodedJSValue, op_lshift) 2537 { 2538 STUB_INIT_STACK_FRAME(stackFrame); 2539 2540 JSValue val = stackFrame.args[0].jsValue(); 2541 JSValue shift = stackFrame.args[1].jsValue(); 2542 2543 CallFrame* callFrame = stackFrame.callFrame; 2544 JSValue result = jsNumber(stackFrame.globalData, (val.toInt32(callFrame)) << (shift.toUInt32(callFrame) & 0x1f)); 2545 CHECK_FOR_EXCEPTION_AT_END(); 2546 return JSValue::encode(result); 2547 } 2548 2549 DEFINE_STUB_FUNCTION(EncodedJSValue, op_bitand) 2550 { 2551 STUB_INIT_STACK_FRAME(stackFrame); 2552 2553 JSValue src1 = stackFrame.args[0].jsValue(); 2554 JSValue src2 = stackFrame.args[1].jsValue(); 2555 2556 ASSERT(!src1.isInt32() || !src2.isInt32()); 2557 CallFrame* callFrame = stackFrame.callFrame; 2558 JSValue result = jsNumber(stackFrame.globalData, src1.toInt32(callFrame) & src2.toInt32(callFrame)); 2559 CHECK_FOR_EXCEPTION_AT_END(); 2560 return JSValue::encode(result); 2561 } 2562 2563 DEFINE_STUB_FUNCTION(EncodedJSValue, op_rshift) 2564 { 2565 STUB_INIT_STACK_FRAME(stackFrame); 2566 2567 JSValue val = stackFrame.args[0].jsValue(); 2568 JSValue shift = stackFrame.args[1].jsValue(); 2569 2570 CallFrame* callFrame = stackFrame.callFrame; 2571 JSValue result = jsNumber(stackFrame.globalData, (val.toInt32(callFrame)) >> (shift.toUInt32(callFrame) & 0x1f)); 2572 2573 CHECK_FOR_EXCEPTION_AT_END(); 2574 return JSValue::encode(result); 2575 } 2576 2577 DEFINE_STUB_FUNCTION(EncodedJSValue, op_bitnot) 2578 { 2579 STUB_INIT_STACK_FRAME(stackFrame); 2580 2581 JSValue src = stackFrame.args[0].jsValue(); 2582 2583 ASSERT(!src.isInt32()); 2584 CallFrame* callFrame = stackFrame.callFrame; 2585 JSValue result = jsNumber(stackFrame.globalData, ~src.toInt32(callFrame)); 2586 CHECK_FOR_EXCEPTION_AT_END(); 2587 return JSValue::encode(result); 2588 } 2589 2590 DEFINE_STUB_FUNCTION(EncodedJSValue, op_resolve_with_base) 2591 { 2592 STUB_INIT_STACK_FRAME(stackFrame); 2593 2594 CallFrame* callFrame = stackFrame.callFrame; 2595 ScopeChainNode* scopeChain = callFrame->scopeChain(); 2596 2597 ScopeChainIterator iter = scopeChain->begin(); 2598 ScopeChainIterator end = scopeChain->end(); 2599 2600 // FIXME: add scopeDepthIsZero optimization 2601 2602 ASSERT(iter != end); 2603 2604 Identifier& ident = stackFrame.args[0].identifier(); 2605 JSObject* base; 2606 do { 2607 base = *iter; 2608 PropertySlot slot(base); 2609 if (base->getPropertySlot(callFrame, ident, slot)) { 2610 JSValue result = slot.getValue(callFrame, ident); 2611 CHECK_FOR_EXCEPTION_AT_END(); 2612 2613 callFrame->registers()[stackFrame.args[1].int32()] = JSValue(base); 2614 return JSValue::encode(result); 2615 } 2616 ++iter; 2617 } while (iter != end); 2618 2619 CodeBlock* codeBlock = callFrame->codeBlock(); 2620 unsigned vPCIndex = codeBlock->getBytecodeIndex(callFrame, STUB_RETURN_ADDRESS); 2621 stackFrame.globalData->exception = createUndefinedVariableError(callFrame, ident, vPCIndex, codeBlock); 2622 VM_THROW_EXCEPTION_AT_END(); 2623 return JSValue::encode(JSValue()); 2624 } 2625 2626 DEFINE_STUB_FUNCTION(JSObject*, op_new_func_exp) 2627 { 2628 STUB_INIT_STACK_FRAME(stackFrame); 2629 CallFrame* callFrame = stackFrame.callFrame; 2630 2631 FunctionExecutable* function = stackFrame.args[0].function(); 2632 JSFunction* func = function->make(callFrame, callFrame->scopeChain()); 2633 2634 /* 2635 The Identifier in a FunctionExpression can be referenced from inside 2636 the FunctionExpression's FunctionBody to allow the function to call 2637 itself recursively. However, unlike in a FunctionDeclaration, the 2638 Identifier in a FunctionExpression cannot be referenced from and 2639 does not affect the scope enclosing the FunctionExpression. 2640 */ 2641 if (!function->name().isNull()) { 2642 JSStaticScopeObject* functionScopeObject = new (callFrame) JSStaticScopeObject(callFrame, function->name(), func, ReadOnly | DontDelete); 2643 func->scope().push(functionScopeObject); 2644 } 2645 2646 return func; 2647 } 2648 2649 DEFINE_STUB_FUNCTION(EncodedJSValue, op_mod) 2650 { 2651 STUB_INIT_STACK_FRAME(stackFrame); 2652 2653 JSValue dividendValue = stackFrame.args[0].jsValue(); 2654 JSValue divisorValue = stackFrame.args[1].jsValue(); 2655 2656 CallFrame* callFrame = stackFrame.callFrame; 2657 double d = dividendValue.toNumber(callFrame); 2658 JSValue result = jsNumber(stackFrame.globalData, fmod(d, divisorValue.toNumber(callFrame))); 2659 CHECK_FOR_EXCEPTION_AT_END(); 2660 return JSValue::encode(result); 2661 } 2662 2663 DEFINE_STUB_FUNCTION(EncodedJSValue, op_less) 2664 { 2665 STUB_INIT_STACK_FRAME(stackFrame); 2666 2667 CallFrame* callFrame = stackFrame.callFrame; 2668 JSValue result = jsBoolean(jsLess(callFrame, stackFrame.args[0].jsValue(), stackFrame.args[1].jsValue())); 2669 CHECK_FOR_EXCEPTION_AT_END(); 2670 return JSValue::encode(result); 2671 } 2672 2673 DEFINE_STUB_FUNCTION(EncodedJSValue, op_post_dec) 2674 { 2675 STUB_INIT_STACK_FRAME(stackFrame); 2676 2677 JSValue v = stackFrame.args[0].jsValue(); 2678 2679 CallFrame* callFrame = stackFrame.callFrame; 2680 2681 JSValue number = v.toJSNumber(callFrame); 2682 CHECK_FOR_EXCEPTION_AT_END(); 2683 2684 callFrame->registers()[stackFrame.args[1].int32()] = jsNumber(stackFrame.globalData, number.uncheckedGetNumber() - 1); 2685 return JSValue::encode(number); 2686 } 2687 2688 DEFINE_STUB_FUNCTION(EncodedJSValue, op_urshift) 2689 { 2690 STUB_INIT_STACK_FRAME(stackFrame); 2691 2692 JSValue val = stackFrame.args[0].jsValue(); 2693 JSValue shift = stackFrame.args[1].jsValue(); 2694 2695 CallFrame* callFrame = stackFrame.callFrame; 2696 JSValue result = jsNumber(stackFrame.globalData, (val.toUInt32(callFrame)) >> (shift.toUInt32(callFrame) & 0x1f)); 2697 CHECK_FOR_EXCEPTION_AT_END(); 2698 return JSValue::encode(result); 2699 } 2700 2701 DEFINE_STUB_FUNCTION(EncodedJSValue, op_bitxor) 2702 { 2703 STUB_INIT_STACK_FRAME(stackFrame); 2704 2705 JSValue src1 = stackFrame.args[0].jsValue(); 2706 JSValue src2 = stackFrame.args[1].jsValue(); 2707 2708 CallFrame* callFrame = stackFrame.callFrame; 2709 2710 JSValue result = jsNumber(stackFrame.globalData, src1.toInt32(callFrame) ^ src2.toInt32(callFrame)); 2711 CHECK_FOR_EXCEPTION_AT_END(); 2712 return JSValue::encode(result); 2713 } 2714 2715 DEFINE_STUB_FUNCTION(JSObject*, op_new_regexp) 2716 { 2717 STUB_INIT_STACK_FRAME(stackFrame); 2718 2719 return new (stackFrame.globalData) RegExpObject(stackFrame.callFrame->lexicalGlobalObject()->regExpStructure(), stackFrame.args[0].regExp()); 2720 } 2721 2722 DEFINE_STUB_FUNCTION(EncodedJSValue, op_bitor) 2723 { 2724 STUB_INIT_STACK_FRAME(stackFrame); 2725 2726 JSValue src1 = stackFrame.args[0].jsValue(); 2727 JSValue src2 = stackFrame.args[1].jsValue(); 2728 2729 CallFrame* callFrame = stackFrame.callFrame; 2730 2731 JSValue result = jsNumber(stackFrame.globalData, src1.toInt32(callFrame) | src2.toInt32(callFrame)); 2732 CHECK_FOR_EXCEPTION_AT_END(); 2733 return JSValue::encode(result); 2734 } 2735 2736 DEFINE_STUB_FUNCTION(EncodedJSValue, op_call_eval) 2737 { 2738 STUB_INIT_STACK_FRAME(stackFrame); 2739 2740 CallFrame* callFrame = stackFrame.callFrame; 2741 RegisterFile* registerFile = stackFrame.registerFile; 2742 2743 Interpreter* interpreter = stackFrame.globalData->interpreter; 2744 2745 JSValue funcVal = stackFrame.args[0].jsValue(); 2746 int registerOffset = stackFrame.args[1].int32(); 2747 int argCount = stackFrame.args[2].int32(); 2748 2749 Register* newCallFrame = callFrame->registers() + registerOffset; 2750 Register* argv = newCallFrame - RegisterFile::CallFrameHeaderSize - argCount; 2751 JSValue thisValue = argv[0].jsValue(); 2752 JSGlobalObject* globalObject = callFrame->scopeChain()->globalObject; 2753 2754 if (thisValue == globalObject && funcVal == globalObject->evalFunction()) { 2755 JSValue exceptionValue; 2756 JSValue result = interpreter->callEval(callFrame, registerFile, argv, argCount, registerOffset, exceptionValue); 2757 if (UNLIKELY(exceptionValue)) { 2758 stackFrame.globalData->exception = exceptionValue; 2759 VM_THROW_EXCEPTION_AT_END(); 2760 } 2761 return JSValue::encode(result); 2762 } 2763 2764 return JSValue::encode(JSValue()); 2765 } 2766 2767 DEFINE_STUB_FUNCTION(EncodedJSValue, op_throw) 2768 { 2769 STUB_INIT_STACK_FRAME(stackFrame); 2770 2771 CallFrame* callFrame = stackFrame.callFrame; 2772 CodeBlock* codeBlock = callFrame->codeBlock(); 2773 2774 unsigned vPCIndex = codeBlock->getBytecodeIndex(callFrame, STUB_RETURN_ADDRESS); 2775 2776 JSValue exceptionValue = stackFrame.args[0].jsValue(); 2777 ASSERT(exceptionValue); 2778 2779 HandlerInfo* handler = stackFrame.globalData->interpreter->throwException(callFrame, exceptionValue, vPCIndex, true); 2780 2781 if (!handler) { 2782 *stackFrame.exception = exceptionValue; 2783 STUB_SET_RETURN_ADDRESS(FunctionPtr(ctiOpThrowNotCaught).value()); 2784 return JSValue::encode(jsNull()); 2785 } 2786 2787 stackFrame.callFrame = callFrame; 2788 void* catchRoutine = handler->nativeCode.executableAddress(); 2789 ASSERT(catchRoutine); 2790 STUB_SET_RETURN_ADDRESS(catchRoutine); 2791 return JSValue::encode(exceptionValue); 2792 } 2793 2794 DEFINE_STUB_FUNCTION(JSPropertyNameIterator*, op_get_pnames) 2795 { 2796 STUB_INIT_STACK_FRAME(stackFrame); 2797 2798 CallFrame* callFrame = stackFrame.callFrame; 2799 JSObject* o = stackFrame.args[0].jsObject(); 2800 Structure* structure = o->structure(); 2801 JSPropertyNameIterator* jsPropertyNameIterator = structure->enumerationCache(); 2802 if (!jsPropertyNameIterator || jsPropertyNameIterator->cachedPrototypeChain() != structure->prototypeChain(callFrame)) 2803 jsPropertyNameIterator = JSPropertyNameIterator::create(callFrame, o); 2804 return jsPropertyNameIterator; 2805 } 2806 2807 DEFINE_STUB_FUNCTION(int, has_property) 2808 { 2809 STUB_INIT_STACK_FRAME(stackFrame); 2810 2811 JSObject* base = stackFrame.args[0].jsObject(); 2812 JSString* property = stackFrame.args[1].jsString(); 2813 return base->hasProperty(stackFrame.callFrame, Identifier(stackFrame.callFrame, property->value(stackFrame.callFrame))); 2814 } 2815 2816 DEFINE_STUB_FUNCTION(JSObject*, op_push_scope) 2817 { 2818 STUB_INIT_STACK_FRAME(stackFrame); 2819 2820 JSObject* o = stackFrame.args[0].jsValue().toObject(stackFrame.callFrame); 2821 CHECK_FOR_EXCEPTION(); 2822 stackFrame.callFrame->setScopeChain(stackFrame.callFrame->scopeChain()->push(o)); 2823 return o; 2824 } 2825 2826 DEFINE_STUB_FUNCTION(void, op_pop_scope) 2827 { 2828 STUB_INIT_STACK_FRAME(stackFrame); 2829 2830 stackFrame.callFrame->setScopeChain(stackFrame.callFrame->scopeChain()->pop()); 2831 } 2832 2833 DEFINE_STUB_FUNCTION(EncodedJSValue, op_typeof) 2834 { 2835 STUB_INIT_STACK_FRAME(stackFrame); 2836 2837 return JSValue::encode(jsTypeStringForValue(stackFrame.callFrame, stackFrame.args[0].jsValue())); 2838 } 2839 2840 DEFINE_STUB_FUNCTION(EncodedJSValue, op_is_undefined) 2841 { 2842 STUB_INIT_STACK_FRAME(stackFrame); 2843 2844 JSValue v = stackFrame.args[0].jsValue(); 2845 return JSValue::encode(jsBoolean(v.isCell() ? v.asCell()->structure()->typeInfo().masqueradesAsUndefined() : v.isUndefined())); 2846 } 2847 2848 DEFINE_STUB_FUNCTION(EncodedJSValue, op_is_boolean) 2849 { 2850 STUB_INIT_STACK_FRAME(stackFrame); 2851 2852 return JSValue::encode(jsBoolean(stackFrame.args[0].jsValue().isBoolean())); 2853 } 2854 2855 DEFINE_STUB_FUNCTION(EncodedJSValue, op_is_number) 2856 { 2857 STUB_INIT_STACK_FRAME(stackFrame); 2858 2859 return JSValue::encode(jsBoolean(stackFrame.args[0].jsValue().isNumber())); 2860 } 2861 2862 DEFINE_STUB_FUNCTION(EncodedJSValue, op_is_string) 2863 { 2864 STUB_INIT_STACK_FRAME(stackFrame); 2865 2866 return JSValue::encode(jsBoolean(isJSString(stackFrame.globalData, stackFrame.args[0].jsValue()))); 2867 } 2868 2869 DEFINE_STUB_FUNCTION(EncodedJSValue, op_is_object) 2870 { 2871 STUB_INIT_STACK_FRAME(stackFrame); 2872 2873 return JSValue::encode(jsBoolean(jsIsObjectType(stackFrame.args[0].jsValue()))); 2874 } 2875 2876 DEFINE_STUB_FUNCTION(EncodedJSValue, op_is_function) 2877 { 2878 STUB_INIT_STACK_FRAME(stackFrame); 2879 2880 return JSValue::encode(jsBoolean(jsIsFunctionType(stackFrame.args[0].jsValue()))); 2881 } 2882 2883 DEFINE_STUB_FUNCTION(EncodedJSValue, op_stricteq) 2884 { 2885 STUB_INIT_STACK_FRAME(stackFrame); 2886 2887 JSValue src1 = stackFrame.args[0].jsValue(); 2888 JSValue src2 = stackFrame.args[1].jsValue(); 2889 2890 return JSValue::encode(jsBoolean(JSValue::strictEqual(stackFrame.callFrame, src1, src2))); 2891 } 2892 2893 DEFINE_STUB_FUNCTION(EncodedJSValue, op_to_primitive) 2894 { 2895 STUB_INIT_STACK_FRAME(stackFrame); 2896 2897 return JSValue::encode(stackFrame.args[0].jsValue().toPrimitive(stackFrame.callFrame)); 2898 } 2899 2900 DEFINE_STUB_FUNCTION(EncodedJSValue, op_strcat) 2901 { 2902 STUB_INIT_STACK_FRAME(stackFrame); 2903 2904 JSValue result = jsString(stackFrame.callFrame, &stackFrame.callFrame->registers()[stackFrame.args[0].int32()], stackFrame.args[1].int32()); 2905 CHECK_FOR_EXCEPTION_AT_END(); 2906 return JSValue::encode(result); 2907 } 2908 2909 DEFINE_STUB_FUNCTION(EncodedJSValue, op_nstricteq) 2910 { 2911 STUB_INIT_STACK_FRAME(stackFrame); 2912 2913 JSValue src1 = stackFrame.args[0].jsValue(); 2914 JSValue src2 = stackFrame.args[1].jsValue(); 2915 2916 return JSValue::encode(jsBoolean(!JSValue::strictEqual(stackFrame.callFrame, src1, src2))); 2917 } 2918 2919 DEFINE_STUB_FUNCTION(EncodedJSValue, op_to_jsnumber) 2920 { 2921 STUB_INIT_STACK_FRAME(stackFrame); 2922 2923 JSValue src = stackFrame.args[0].jsValue(); 2924 CallFrame* callFrame = stackFrame.callFrame; 2925 2926 JSValue result = src.toJSNumber(callFrame); 2927 CHECK_FOR_EXCEPTION_AT_END(); 2928 return JSValue::encode(result); 2929 } 2930 2931 DEFINE_STUB_FUNCTION(EncodedJSValue, op_in) 2932 { 2933 STUB_INIT_STACK_FRAME(stackFrame); 2934 2935 CallFrame* callFrame = stackFrame.callFrame; 2936 JSValue baseVal = stackFrame.args[1].jsValue(); 2937 2938 if (!baseVal.isObject()) { 2939 CallFrame* callFrame = stackFrame.callFrame; 2940 CodeBlock* codeBlock = callFrame->codeBlock(); 2941 unsigned vPCIndex = codeBlock->getBytecodeIndex(callFrame, STUB_RETURN_ADDRESS); 2942 stackFrame.globalData->exception = createInvalidParamError(callFrame, "in", baseVal, vPCIndex, codeBlock); 2943 VM_THROW_EXCEPTION(); 2944 } 2945 2946 JSValue propName = stackFrame.args[0].jsValue(); 2947 JSObject* baseObj = asObject(baseVal); 2948 2949 uint32_t i; 2950 if (propName.getUInt32(i)) 2951 return JSValue::encode(jsBoolean(baseObj->hasProperty(callFrame, i))); 2952 2953 Identifier property(callFrame, propName.toString(callFrame)); 2954 CHECK_FOR_EXCEPTION(); 2955 return JSValue::encode(jsBoolean(baseObj->hasProperty(callFrame, property))); 2956 } 2957 2958 DEFINE_STUB_FUNCTION(JSObject*, op_push_new_scope) 2959 { 2960 STUB_INIT_STACK_FRAME(stackFrame); 2961 2962 JSObject* scope = new (stackFrame.globalData) JSStaticScopeObject(stackFrame.callFrame, stackFrame.args[0].identifier(), stackFrame.args[1].jsValue(), DontDelete); 2963 2964 CallFrame* callFrame = stackFrame.callFrame; 2965 callFrame->setScopeChain(callFrame->scopeChain()->push(scope)); 2966 return scope; 2967 } 2968 2969 DEFINE_STUB_FUNCTION(void, op_jmp_scopes) 2970 { 2971 STUB_INIT_STACK_FRAME(stackFrame); 2972 2973 unsigned count = stackFrame.args[0].int32(); 2974 CallFrame* callFrame = stackFrame.callFrame; 2975 2976 ScopeChainNode* tmp = callFrame->scopeChain(); 2977 while (count--) 2978 tmp = tmp->pop(); 2979 callFrame->setScopeChain(tmp); 2980 } 2981 2982 DEFINE_STUB_FUNCTION(void, op_put_by_index) 2983 { 2984 STUB_INIT_STACK_FRAME(stackFrame); 2985 2986 CallFrame* callFrame = stackFrame.callFrame; 2987 unsigned property = stackFrame.args[1].int32(); 2988 2989 stackFrame.args[0].jsValue().put(callFrame, property, stackFrame.args[2].jsValue()); 2990 } 2991 2992 DEFINE_STUB_FUNCTION(void*, op_switch_imm) 2993 { 2994 STUB_INIT_STACK_FRAME(stackFrame); 2995 2996 JSValue scrutinee = stackFrame.args[0].jsValue(); 2997 unsigned tableIndex = stackFrame.args[1].int32(); 2998 CallFrame* callFrame = stackFrame.callFrame; 2999 CodeBlock* codeBlock = callFrame->codeBlock(); 3000 3001 if (scrutinee.isInt32()) 3002 return codeBlock->immediateSwitchJumpTable(tableIndex).ctiForValue(scrutinee.asInt32()).executableAddress(); 3003 else { 3004 double value; 3005 int32_t intValue; 3006 if (scrutinee.getNumber(value) && ((intValue = static_cast<int32_t>(value)) == value)) 3007 return codeBlock->immediateSwitchJumpTable(tableIndex).ctiForValue(intValue).executableAddress(); 3008 else 3009 return codeBlock->immediateSwitchJumpTable(tableIndex).ctiDefault.executableAddress(); 3010 } 3011 } 3012 3013 DEFINE_STUB_FUNCTION(void*, op_switch_char) 3014 { 3015 STUB_INIT_STACK_FRAME(stackFrame); 3016 3017 JSValue scrutinee = stackFrame.args[0].jsValue(); 3018 unsigned tableIndex = stackFrame.args[1].int32(); 3019 CallFrame* callFrame = stackFrame.callFrame; 3020 CodeBlock* codeBlock = callFrame->codeBlock(); 3021 3022 void* result = codeBlock->characterSwitchJumpTable(tableIndex).ctiDefault.executableAddress(); 3023 3024 if (scrutinee.isString()) { 3025 UString::Rep* value = asString(scrutinee)->value(callFrame).rep(); 3026 if (value->size() == 1) 3027 result = codeBlock->characterSwitchJumpTable(tableIndex).ctiForValue(value->data()[0]).executableAddress(); 3028 } 3029 3030 return result; 3031 } 3032 3033 DEFINE_STUB_FUNCTION(void*, op_switch_string) 3034 { 3035 STUB_INIT_STACK_FRAME(stackFrame); 3036 3037 JSValue scrutinee = stackFrame.args[0].jsValue(); 3038 unsigned tableIndex = stackFrame.args[1].int32(); 3039 CallFrame* callFrame = stackFrame.callFrame; 3040 CodeBlock* codeBlock = callFrame->codeBlock(); 3041 3042 void* result = codeBlock->stringSwitchJumpTable(tableIndex).ctiDefault.executableAddress(); 3043 3044 if (scrutinee.isString()) { 3045 UString::Rep* value = asString(scrutinee)->value(callFrame).rep(); 3046 result = codeBlock->stringSwitchJumpTable(tableIndex).ctiForValue(value).executableAddress(); 3047 } 3048 3049 return result; 3050 } 3051 3052 DEFINE_STUB_FUNCTION(EncodedJSValue, op_del_by_val) 3053 { 3054 STUB_INIT_STACK_FRAME(stackFrame); 3055 3056 CallFrame* callFrame = stackFrame.callFrame; 3057 3058 JSValue baseValue = stackFrame.args[0].jsValue(); 3059 JSObject* baseObj = baseValue.toObject(callFrame); // may throw 3060 3061 JSValue subscript = stackFrame.args[1].jsValue(); 3062 JSValue result; 3063 uint32_t i; 3064 if (subscript.getUInt32(i)) 3065 result = jsBoolean(baseObj->deleteProperty(callFrame, i)); 3066 else { 3067 CHECK_FOR_EXCEPTION(); 3068 Identifier property(callFrame, subscript.toString(callFrame)); 3069 CHECK_FOR_EXCEPTION(); 3070 result = jsBoolean(baseObj->deleteProperty(callFrame, property)); 3071 } 3072 3073 CHECK_FOR_EXCEPTION_AT_END(); 3074 return JSValue::encode(result); 3075 } 3076 3077 DEFINE_STUB_FUNCTION(void, op_put_getter) 3078 { 3079 STUB_INIT_STACK_FRAME(stackFrame); 3080 3081 CallFrame* callFrame = stackFrame.callFrame; 3082 3083 ASSERT(stackFrame.args[0].jsValue().isObject()); 3084 JSObject* baseObj = asObject(stackFrame.args[0].jsValue()); 3085 ASSERT(stackFrame.args[2].jsValue().isObject()); 3086 baseObj->defineGetter(callFrame, stackFrame.args[1].identifier(), asObject(stackFrame.args[2].jsValue())); 3087 } 3088 3089 DEFINE_STUB_FUNCTION(void, op_put_setter) 3090 { 3091 STUB_INIT_STACK_FRAME(stackFrame); 3092 3093 CallFrame* callFrame = stackFrame.callFrame; 3094 3095 ASSERT(stackFrame.args[0].jsValue().isObject()); 3096 JSObject* baseObj = asObject(stackFrame.args[0].jsValue()); 3097 ASSERT(stackFrame.args[2].jsValue().isObject()); 3098 baseObj->defineSetter(callFrame, stackFrame.args[1].identifier(), asObject(stackFrame.args[2].jsValue())); 3099 } 3100 3101 DEFINE_STUB_FUNCTION(JSObject*, op_new_error) 3102 { 3103 STUB_INIT_STACK_FRAME(stackFrame); 3104 3105 CallFrame* callFrame = stackFrame.callFrame; 3106 CodeBlock* codeBlock = callFrame->codeBlock(); 3107 unsigned type = stackFrame.args[0].int32(); 3108 JSValue message = stackFrame.args[1].jsValue(); 3109 unsigned bytecodeOffset = stackFrame.args[2].int32(); 3110 3111 unsigned lineNumber = codeBlock->lineNumberForBytecodeOffset(callFrame, bytecodeOffset); 3112 return Error::create(callFrame, static_cast<ErrorType>(type), message.toString(callFrame), lineNumber, codeBlock->ownerExecutable()->sourceID(), codeBlock->ownerExecutable()->sourceURL()); 3113 } 3114 3115 DEFINE_STUB_FUNCTION(void, op_debug) 3116 { 3117 STUB_INIT_STACK_FRAME(stackFrame); 3118 3119 CallFrame* callFrame = stackFrame.callFrame; 3120 3121 int debugHookID = stackFrame.args[0].int32(); 3122 int firstLine = stackFrame.args[1].int32(); 3123 int lastLine = stackFrame.args[2].int32(); 3124 3125 stackFrame.globalData->interpreter->debug(callFrame, static_cast<DebugHookID>(debugHookID), firstLine, lastLine); 3126 } 3127 3128 DEFINE_STUB_FUNCTION(EncodedJSValue, vm_throw) 3129 { 3130 STUB_INIT_STACK_FRAME(stackFrame); 3131 3132 CallFrame* callFrame = stackFrame.callFrame; 3133 CodeBlock* codeBlock = callFrame->codeBlock(); 3134 JSGlobalData* globalData = stackFrame.globalData; 3135 3136 unsigned vPCIndex = codeBlock->getBytecodeIndex(callFrame, globalData->exceptionLocation); 3137 3138 JSValue exceptionValue = globalData->exception; 3139 ASSERT(exceptionValue); 3140 globalData->exception = JSValue(); 3141 3142 HandlerInfo* handler = globalData->interpreter->throwException(callFrame, exceptionValue, vPCIndex, false); 3143 3144 if (!handler) { 3145 *stackFrame.exception = exceptionValue; 3146 return JSValue::encode(jsNull()); 3147 } 3148 3149 stackFrame.callFrame = callFrame; 3150 void* catchRoutine = handler->nativeCode.executableAddress(); 3151 ASSERT(catchRoutine); 3152 STUB_SET_RETURN_ADDRESS(catchRoutine); 3153 return JSValue::encode(exceptionValue); 3154 } 3155 3156 DEFINE_STUB_FUNCTION(EncodedJSValue, to_object) 3157 { 3158 STUB_INIT_STACK_FRAME(stackFrame); 3159 3160 CallFrame* callFrame = stackFrame.callFrame; 3161 return JSValue::encode(stackFrame.args[0].jsValue().toObject(callFrame)); 3162 } 3163 3164 } // namespace JSC 3165 3166 #endif // ENABLE(JIT) 3167