Build fix attempt after r154156.
[WebKit-https.git] / Source / JavaScriptCore / jit / JITStubs.cpp
1 /*
2  * Copyright (C) 2008, 2009, 2013 Apple Inc. All rights reserved.
3  * Copyright (C) 2008 Cameron Zwarich <cwzwarich@uwaterloo.ca>
4  * Copyright (C) Research In Motion Limited 2010, 2011. All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  *
10  * 1.  Redistributions of source code must retain the above copyright
11  *     notice, this list of conditions and the following disclaimer.
12  * 2.  Redistributions in binary form must reproduce the above copyright
13  *     notice, this list of conditions and the following disclaimer in the
14  *     documentation and/or other materials provided with the distribution.
15  * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
16  *     its contributors may be used to endorse or promote products derived
17  *     from this software without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
20  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22  * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
23  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
26  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29  */
30
31 #include "config.h"
32
33 #if ENABLE(JIT)
34 #include "JITStubs.h"
35
36 #include "Arguments.h"
37 #include "ArrayConstructor.h"
38 #include "CallFrame.h"
39 #include "CallFrameInlines.h"
40 #include "CodeBlock.h"
41 #include "CodeProfiling.h"
42 #include "CommonSlowPaths.h"
43 #include "DFGOSREntry.h"
44 #include "DFGWorklist.h"
45 #include "Debugger.h"
46 #include "DeferGC.h"
47 #include "ExceptionHelpers.h"
48 #include "GetterSetter.h"
49 #include "Heap.h"
50 #include <wtf/InlineASM.h>
51 #include "JIT.h"
52 #include "JITExceptions.h"
53 #include "JSActivation.h"
54 #include "JSArray.h"
55 #include "JSFunction.h"
56 #include "JSGlobalObjectFunctions.h"
57 #include "JSNameScope.h"
58 #include "JSNotAnObject.h"
59 #include "JSPropertyNameIterator.h"
60 #include "JSString.h"
61 #include "JSWithScope.h"
62 #include "LegacyProfiler.h"
63 #include "NameInstance.h"
64 #include "ObjectConstructor.h"
65 #include "ObjectPrototype.h"
66 #include "Operations.h"
67 #include "Parser.h"
68 #include "RegExpObject.h"
69 #include "RegExpPrototype.h"
70 #include "Register.h"
71 #include "RepatchBuffer.h"
72 #include "SamplingTool.h"
73 #include "SlowPathCall.h"
74 #include "Strong.h"
75 #include "StructureRareDataInlines.h"
76 #include <wtf/StdLibExtras.h>
77 #include <stdarg.h>
78 #include <stdio.h>
79
80 using namespace std;
81
82 #if CPU(ARM_TRADITIONAL)
83 #include "JITStubsARM.h"
84 #elif CPU(ARM_THUMB2)
85 #include "JITStubsARMv7.h"
86 #elif CPU(MIPS)
87 #include "JITStubsMIPS.h"
88 #elif CPU(SH4)
89 #include "JITStubsSH4.h"
90 #elif CPU(X86)
91 #include "JITStubsX86.h"
92 #elif CPU(X86_64)
93 #include "JITStubsX86_64.h"
94 #else
95 #error "JIT not supported on this platform."
96 #endif
97
98 namespace JSC {
99
100 #if ENABLE(OPCODE_SAMPLING)
101     #define CTI_SAMPLER stackFrame.vm->interpreter->sampler()
102 #else
103     #define CTI_SAMPLER 0
104 #endif
105
106 void performPlatformSpecificJITAssertions(VM* vm)
107 {
108     if (!vm->canUseJIT())
109         return;
110
111 #if CPU(ARM_THUMB2)
112     performARMv7JITAssertions();
113 #elif CPU(ARM_TRADITIONAL)
114     performARMJITAssertions();
115 #elif CPU(MIPS)
116     performMIPSJITAssertions();
117 #elif CPU(SH4)
118     performSH4JITAssertions();
119 #endif
120 }
121
122 NEVER_INLINE static void tryCachePutByID(CallFrame* callFrame, CodeBlock* codeBlock, ReturnAddressPtr returnAddress, JSValue baseValue, const PutPropertySlot& slot, StructureStubInfo* stubInfo, bool direct)
123 {
124     ConcurrentJITLocker locker(codeBlock->m_lock);
125     
126     // The interpreter checks for recursion here; I do not believe this can occur in CTI.
127
128     if (!baseValue.isCell())
129         return;
130
131     // Uncacheable: give up.
132     if (!slot.isCacheable()) {
133         ctiPatchCallByReturnAddress(codeBlock, returnAddress, FunctionPtr(direct ? cti_op_put_by_id_direct_generic : cti_op_put_by_id_generic));
134         return;
135     }
136     
137     JSCell* baseCell = baseValue.asCell();
138     Structure* structure = baseCell->structure();
139
140     if (structure->isUncacheableDictionary() || structure->typeInfo().prohibitsPropertyCaching()) {
141         ctiPatchCallByReturnAddress(codeBlock, returnAddress, FunctionPtr(direct ? cti_op_put_by_id_direct_generic : cti_op_put_by_id_generic));
142         return;
143     }
144
145     // If baseCell != base, then baseCell must be a proxy for another object.
146     if (baseCell != slot.base()) {
147         ctiPatchCallByReturnAddress(codeBlock, returnAddress, FunctionPtr(direct ? cti_op_put_by_id_direct_generic : cti_op_put_by_id_generic));
148         return;
149     }
150
151     // Cache hit: Specialize instruction and ref Structures.
152
153     // Structure transition, cache transition info
154     if (slot.type() == PutPropertySlot::NewProperty) {
155         if (structure->isDictionary()) {
156             ctiPatchCallByReturnAddress(codeBlock, returnAddress, FunctionPtr(direct ? cti_op_put_by_id_direct_generic : cti_op_put_by_id_generic));
157             return;
158         }
159
160         // put_by_id_transition checks the prototype chain for setters.
161         if (normalizePrototypeChain(callFrame, baseCell) == InvalidPrototypeChain) {
162             ctiPatchCallByReturnAddress(codeBlock, returnAddress, FunctionPtr(direct ? cti_op_put_by_id_direct_generic : cti_op_put_by_id_generic));
163             return;
164         }
165
166         StructureChain* prototypeChain = structure->prototypeChain(callFrame);
167         ASSERT(structure->previousID()->transitionWatchpointSetHasBeenInvalidated());
168         stubInfo->initPutByIdTransition(callFrame->vm(), codeBlock->ownerExecutable(), structure->previousID(), structure, prototypeChain, direct);
169         JIT::compilePutByIdTransition(callFrame->scope()->vm(), codeBlock, stubInfo, structure->previousID(), structure, slot.cachedOffset(), prototypeChain, returnAddress, direct);
170         return;
171     }
172     
173     stubInfo->initPutByIdReplace(callFrame->vm(), codeBlock->ownerExecutable(), structure);
174
175     JIT::patchPutByIdReplace(codeBlock, stubInfo, structure, slot.cachedOffset(), returnAddress, direct);
176 }
177
178 NEVER_INLINE static void tryCacheGetByID(CallFrame* callFrame, CodeBlock* codeBlock, ReturnAddressPtr returnAddress, JSValue baseValue, const Identifier& propertyName, const PropertySlot& slot, StructureStubInfo* stubInfo)
179 {
180     ConcurrentJITLocker locker(codeBlock->m_lock);
181     
182     // FIXME: Write a test that proves we need to check for recursion here just
183     // like the interpreter does, then add a check for recursion.
184
185     // FIXME: Cache property access for immediates.
186     if (!baseValue.isCell()) {
187         ctiPatchCallByReturnAddress(codeBlock, returnAddress, FunctionPtr(cti_op_get_by_id_generic));
188         return;
189     }
190     
191     VM* vm = &callFrame->vm();
192
193     if (isJSArray(baseValue) && propertyName == callFrame->propertyNames().length) {
194         JIT::compilePatchGetArrayLength(callFrame->scope()->vm(), codeBlock, returnAddress);
195         return;
196     }
197     
198     if (isJSString(baseValue) && propertyName == callFrame->propertyNames().length) {
199         // The tradeoff of compiling an patched inline string length access routine does not seem
200         // to pay off, so we currently only do this for arrays.
201         ctiPatchCallByReturnAddress(codeBlock, returnAddress, vm->getCTIStub(stringLengthTrampolineGenerator).code());
202         return;
203     }
204
205     // Uncacheable: give up.
206     if (!slot.isCacheable()) {
207         stubInfo->accessType = access_get_by_id_generic;
208         ctiPatchCallByReturnAddress(codeBlock, returnAddress, FunctionPtr(cti_op_get_by_id_generic));
209         return;
210     }
211
212     JSCell* baseCell = baseValue.asCell();
213     Structure* structure = baseCell->structure();
214
215     if (structure->isUncacheableDictionary() || structure->typeInfo().prohibitsPropertyCaching()) {
216         stubInfo->accessType = access_get_by_id_generic;
217         ctiPatchCallByReturnAddress(codeBlock, returnAddress, FunctionPtr(cti_op_get_by_id_generic));
218         return;
219     }
220
221     // Cache hit: Specialize instruction and ref Structures.
222
223     if (slot.slotBase() == baseValue) {
224         RELEASE_ASSERT(stubInfo->accessType == access_unset);
225         if (!slot.isCacheableValue() || !MacroAssembler::isCompactPtrAlignedAddressOffset(maxOffsetRelativeToPatchedStorage(slot.cachedOffset())))
226             ctiPatchCallByReturnAddress(codeBlock, returnAddress, FunctionPtr(cti_op_get_by_id_self_fail));
227         else {
228             JIT::patchGetByIdSelf(codeBlock, stubInfo, structure, slot.cachedOffset(), returnAddress);
229             stubInfo->initGetByIdSelf(callFrame->vm(), codeBlock->ownerExecutable(), structure);
230         }
231         return;
232     }
233
234     if (structure->isDictionary()) {
235         stubInfo->accessType = access_get_by_id_generic;
236         ctiPatchCallByReturnAddress(codeBlock, returnAddress, FunctionPtr(cti_op_get_by_id_generic));
237         return;
238     }
239
240     if (slot.slotBase() == structure->prototypeForLookup(callFrame)) {
241         JSObject* slotBaseObject = asObject(slot.slotBase());
242         size_t offset = slot.cachedOffset();
243
244         if (structure->typeInfo().hasImpureGetOwnPropertySlot()) {
245             stubInfo->accessType = access_get_by_id_generic;
246             ctiPatchCallByReturnAddress(codeBlock, returnAddress, FunctionPtr(cti_op_get_by_id_generic));
247             return;
248         }
249         
250         // Since we're accessing a prototype in a loop, it's a good bet that it
251         // should not be treated as a dictionary.
252         if (slotBaseObject->structure()->isDictionary()) {
253             slotBaseObject->flattenDictionaryObject(callFrame->vm());
254             offset = slotBaseObject->structure()->get(callFrame->vm(), propertyName);
255         }
256         
257         stubInfo->initGetByIdProto(callFrame->vm(), codeBlock->ownerExecutable(), structure, slotBaseObject->structure(), slot.isCacheableValue());
258
259         ASSERT(!structure->isDictionary());
260         ASSERT(!slotBaseObject->structure()->isDictionary());
261         JIT::compileGetByIdProto(callFrame->scope()->vm(), callFrame, codeBlock, stubInfo, structure, slotBaseObject->structure(), propertyName, slot, offset, returnAddress);
262         return;
263     }
264
265     PropertyOffset offset = slot.cachedOffset();
266     size_t count = normalizePrototypeChainForChainAccess(callFrame, baseValue, slot.slotBase(), propertyName, offset);
267     if (count == InvalidPrototypeChain) {
268         stubInfo->accessType = access_get_by_id_generic;
269         ctiPatchCallByReturnAddress(codeBlock, returnAddress, FunctionPtr(cti_op_get_by_id_generic));
270         return;
271     }
272
273     StructureChain* prototypeChain = structure->prototypeChain(callFrame);
274     stubInfo->initGetByIdChain(callFrame->vm(), codeBlock->ownerExecutable(), structure, prototypeChain, count, slot.isCacheableValue());
275     JIT::compileGetByIdChain(callFrame->scope()->vm(), callFrame, codeBlock, stubInfo, structure, prototypeChain, count, propertyName, slot, offset, returnAddress);
276 }
277
278 #if !defined(NDEBUG)
279
280 extern "C" {
281
282 static void jscGeneratedNativeCode() 
283 {
284     // When executing a JIT stub function (which might do an allocation), we hack the return address
285     // to pretend to be executing this function, to keep stack logging tools from blowing out
286     // memory.
287 }
288
289 }
290
291 struct StackHack {
292     ALWAYS_INLINE StackHack(JITStackFrame& stackFrame) 
293         : stackFrame(stackFrame)
294         , savedReturnAddress(*stackFrame.returnAddressSlot())
295     {
296         if (!CodeProfiling::enabled())
297             *stackFrame.returnAddressSlot() = ReturnAddressPtr(FunctionPtr(jscGeneratedNativeCode));
298     }
299
300     ALWAYS_INLINE ~StackHack() 
301     { 
302         *stackFrame.returnAddressSlot() = savedReturnAddress;
303     }
304
305     JITStackFrame& stackFrame;
306     ReturnAddressPtr savedReturnAddress;
307 };
308
309 #define STUB_INIT_STACK_FRAME(stackFrame) JITStackFrame& stackFrame = *reinterpret_cast_ptr<JITStackFrame*>(STUB_ARGS); StackHack stackHack(stackFrame)
310 #define STUB_SET_RETURN_ADDRESS(returnAddress) stackHack.savedReturnAddress = ReturnAddressPtr(returnAddress)
311 #define STUB_RETURN_ADDRESS stackHack.savedReturnAddress
312
313 #else
314
315 #define STUB_INIT_STACK_FRAME(stackFrame) JITStackFrame& stackFrame = *reinterpret_cast_ptr<JITStackFrame*>(STUB_ARGS)
316 #define STUB_SET_RETURN_ADDRESS(returnAddress) *stackFrame.returnAddressSlot() = ReturnAddressPtr(returnAddress)
317 #define STUB_RETURN_ADDRESS *stackFrame.returnAddressSlot()
318
319 #endif
320
321 // The reason this is not inlined is to avoid having to do a PIC branch
322 // to get the address of the ctiVMThrowTrampoline function. It's also
323 // good to keep the code size down by leaving as much of the exception
324 // handling code out of line as possible.
325 static NEVER_INLINE void returnToThrowTrampoline(VM* vm, ReturnAddressPtr exceptionLocation, ReturnAddressPtr& returnAddressSlot)
326 {
327     RELEASE_ASSERT(vm->exception);
328     vm->exceptionLocation = exceptionLocation;
329     returnAddressSlot = ReturnAddressPtr(FunctionPtr(ctiVMThrowTrampoline));
330 }
331
332 #define VM_THROW_EXCEPTION() \
333     do { \
334         VM_THROW_EXCEPTION_AT_END(); \
335         return 0; \
336     } while (0)
337 #define VM_THROW_EXCEPTION_AT_END() \
338     do {\
339         returnToThrowTrampoline(stackFrame.vm, STUB_RETURN_ADDRESS, STUB_RETURN_ADDRESS);\
340     } while (0)
341
342 #define CHECK_FOR_EXCEPTION() \
343     do { \
344         if (UNLIKELY(stackFrame.vm->exception)) \
345             VM_THROW_EXCEPTION(); \
346     } while (0)
347 #define CHECK_FOR_EXCEPTION_AT_END() \
348     do { \
349         if (UNLIKELY(stackFrame.vm->exception)) \
350             VM_THROW_EXCEPTION_AT_END(); \
351     } while (0)
352 #define CHECK_FOR_EXCEPTION_VOID() \
353     do { \
354         if (UNLIKELY(stackFrame.vm->exception)) { \
355             VM_THROW_EXCEPTION_AT_END(); \
356             return; \
357         } \
358     } while (0)
359
360 class ErrorFunctor {
361 public:
362     virtual ~ErrorFunctor() { }
363     virtual JSValue operator()(ExecState*) = 0;
364 };
365
366 class ErrorWithExecFunctor : public ErrorFunctor {
367 public:
368     typedef JSObject* (*Factory)(ExecState* exec);
369     
370     ErrorWithExecFunctor(Factory factory)
371         : m_factory(factory)
372     {
373     }
374     JSValue operator()(ExecState* exec)
375     {
376         return m_factory(exec);
377     }
378
379 private:
380     Factory m_factory;
381 };
382
383 class ErrorWithExecAndCalleeFunctor : public ErrorFunctor {
384 public:
385     typedef JSObject* (*Factory)(ExecState* exec, JSValue callee);
386
387     ErrorWithExecAndCalleeFunctor(Factory factory, JSValue callee)
388         : m_factory(factory), m_callee(callee)
389     {
390     }
391     JSValue operator()(ExecState* exec)
392     {
393         return m_factory(exec, m_callee);
394     }
395 private:
396     Factory m_factory;
397     JSValue m_callee;
398 };
399
400 class ErrorWithExceptionFunctor : public ErrorFunctor {
401     public:
402     ErrorWithExceptionFunctor(JSValue exception)
403         : m_exception(exception)
404     {
405     }
406     JSValue operator()(ExecState*)
407     {
408     return m_exception;
409     }
410
411 private:
412     JSValue m_exception;
413 };
414
415 // Helper function for JIT stubs that may throw an exception in the middle of
416 // processing a function call. This function rolls back the stack to
417 // our caller, so exception processing can proceed from a valid state.
418 template<typename T> static T throwExceptionFromOpCall(JITStackFrame& jitStackFrame, CallFrame* newCallFrame, ReturnAddressPtr& returnAddressSlot, ErrorFunctor& createError )
419 {
420     CallFrame* callFrame = newCallFrame->callerFrame()->removeHostCallFrameFlag();
421     jitStackFrame.callFrame = callFrame;
422     callFrame->vm().topCallFrame = callFrame;
423     callFrame->vm().exception = createError(callFrame);
424     ASSERT(callFrame->vm().exception);
425     returnToThrowTrampoline(&callFrame->vm(), ReturnAddressPtr(newCallFrame->returnPC()), returnAddressSlot);
426     return T();
427 }
428
429 template<typename T> static T throwExceptionFromOpCall(JITStackFrame& jitStackFrame, CallFrame* newCallFrame, ReturnAddressPtr& returnAddressSlot)
430 {
431     CallFrame* callFrame = newCallFrame->callerFrame();
432     ASSERT(callFrame->vm().exception);
433     ErrorWithExceptionFunctor functor = ErrorWithExceptionFunctor(callFrame->vm().exception);
434     return throwExceptionFromOpCall<T>(jitStackFrame, newCallFrame, returnAddressSlot, functor);
435 }
436
437 // If the CPU specific header does not provide an implementation, use the default one here.
438 #ifndef DEFINE_STUB_FUNCTION
439 #define DEFINE_STUB_FUNCTION(rtype, op) rtype JIT_STUB cti_##op(STUB_ARGS_DECLARATION)
440 #endif
441
442 DEFINE_STUB_FUNCTION(void, handle_watchdog_timer)
443 {
444     STUB_INIT_STACK_FRAME(stackFrame);
445     CallFrame* callFrame = stackFrame.callFrame;
446     VM* vm = stackFrame.vm;
447     if (UNLIKELY(vm->watchdog.didFire(callFrame))) {
448         vm->exception = createTerminatedExecutionException(vm);
449         VM_THROW_EXCEPTION_AT_END();
450         return;
451     }
452 }
453
454 DEFINE_STUB_FUNCTION(void*, stack_check)
455 {
456     STUB_INIT_STACK_FRAME(stackFrame);
457     CallFrame* callFrame = stackFrame.callFrame;
458
459     if (UNLIKELY(!stackFrame.stack->grow(&callFrame->registers()[callFrame->codeBlock()->m_numCalleeRegisters]))) {
460         ErrorWithExecFunctor functor = ErrorWithExecFunctor(createStackOverflowError);
461         return throwExceptionFromOpCall<void*>(stackFrame, callFrame, STUB_RETURN_ADDRESS, functor);
462     }
463
464     return callFrame;
465 }
466
467 DEFINE_STUB_FUNCTION(JSObject*, op_new_object)
468 {
469     STUB_INIT_STACK_FRAME(stackFrame);
470
471     return constructEmptyObject(stackFrame.callFrame, stackFrame.args[0].structure());
472 }
473
474 DEFINE_STUB_FUNCTION(void, op_put_by_id_generic)
475 {
476     STUB_INIT_STACK_FRAME(stackFrame);
477
478     PutPropertySlot slot(stackFrame.callFrame->codeBlock()->isStrictMode());
479     stackFrame.args[0].jsValue().put(stackFrame.callFrame, stackFrame.args[1].identifier(), stackFrame.args[2].jsValue(), slot);
480     CHECK_FOR_EXCEPTION_AT_END();
481 }
482
483 DEFINE_STUB_FUNCTION(void, op_put_by_id_direct_generic)
484 {
485     STUB_INIT_STACK_FRAME(stackFrame);
486     
487     PutPropertySlot slot(stackFrame.callFrame->codeBlock()->isStrictMode());
488     JSValue baseValue = stackFrame.args[0].jsValue();
489     ASSERT(baseValue.isObject());
490     asObject(baseValue)->putDirect(stackFrame.callFrame->vm(), stackFrame.args[1].identifier(), stackFrame.args[2].jsValue(), slot);
491     CHECK_FOR_EXCEPTION_AT_END();
492 }
493
494 DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_id_generic)
495 {
496     STUB_INIT_STACK_FRAME(stackFrame);
497
498     CallFrame* callFrame = stackFrame.callFrame;
499     Identifier& ident = stackFrame.args[1].identifier();
500
501     JSValue baseValue = stackFrame.args[0].jsValue();
502     PropertySlot slot(baseValue);
503     JSValue result = baseValue.get(callFrame, ident, slot);
504
505     CHECK_FOR_EXCEPTION_AT_END();
506     return JSValue::encode(result);
507 }
508
509 DEFINE_STUB_FUNCTION(void, op_put_by_id)
510 {
511     STUB_INIT_STACK_FRAME(stackFrame);
512     CallFrame* callFrame = stackFrame.callFrame;
513     Identifier& ident = stackFrame.args[1].identifier();
514     
515     CodeBlock* codeBlock = stackFrame.callFrame->codeBlock();
516     StructureStubInfo* stubInfo = &codeBlock->getStubInfo(STUB_RETURN_ADDRESS);
517     AccessType accessType = static_cast<AccessType>(stubInfo->accessType);
518
519     PutPropertySlot slot(callFrame->codeBlock()->isStrictMode());
520     stackFrame.args[0].jsValue().put(callFrame, ident, stackFrame.args[2].jsValue(), slot);
521     
522     if (accessType == static_cast<AccessType>(stubInfo->accessType)) {
523         stubInfo->setSeen();
524         tryCachePutByID(callFrame, codeBlock, STUB_RETURN_ADDRESS, stackFrame.args[0].jsValue(), slot, stubInfo, false);
525     }
526     
527     CHECK_FOR_EXCEPTION_AT_END();
528 }
529
530 DEFINE_STUB_FUNCTION(void, op_put_by_id_direct)
531 {
532     STUB_INIT_STACK_FRAME(stackFrame);
533     CallFrame* callFrame = stackFrame.callFrame;
534     Identifier& ident = stackFrame.args[1].identifier();
535     
536     CodeBlock* codeBlock = stackFrame.callFrame->codeBlock();
537     StructureStubInfo* stubInfo = &codeBlock->getStubInfo(STUB_RETURN_ADDRESS);
538     AccessType accessType = static_cast<AccessType>(stubInfo->accessType);
539
540     PutPropertySlot slot(callFrame->codeBlock()->isStrictMode());
541     JSValue baseValue = stackFrame.args[0].jsValue();
542     ASSERT(baseValue.isObject());
543     
544     asObject(baseValue)->putDirect(callFrame->vm(), ident, stackFrame.args[2].jsValue(), slot);
545     
546     if (accessType == static_cast<AccessType>(stubInfo->accessType)) {
547         stubInfo->setSeen();
548         tryCachePutByID(callFrame, codeBlock, STUB_RETURN_ADDRESS, stackFrame.args[0].jsValue(), slot, stubInfo, true);
549     }
550     
551     CHECK_FOR_EXCEPTION_AT_END();
552 }
553
554 DEFINE_STUB_FUNCTION(void, op_put_by_id_fail)
555 {
556     STUB_INIT_STACK_FRAME(stackFrame);
557
558     CallFrame* callFrame = stackFrame.callFrame;
559     Identifier& ident = stackFrame.args[1].identifier();
560     
561     PutPropertySlot slot(callFrame->codeBlock()->isStrictMode());
562     stackFrame.args[0].jsValue().put(callFrame, ident, stackFrame.args[2].jsValue(), slot);
563
564     CHECK_FOR_EXCEPTION_AT_END();
565 }
566
567 DEFINE_STUB_FUNCTION(void, op_put_by_id_direct_fail)
568 {
569     STUB_INIT_STACK_FRAME(stackFrame);
570     
571     CallFrame* callFrame = stackFrame.callFrame;
572     Identifier& ident = stackFrame.args[1].identifier();
573     
574     PutPropertySlot slot(callFrame->codeBlock()->isStrictMode());
575     JSValue baseValue = stackFrame.args[0].jsValue();
576     ASSERT(baseValue.isObject());
577     asObject(baseValue)->putDirect(callFrame->vm(), ident, stackFrame.args[2].jsValue(), slot);
578     
579     CHECK_FOR_EXCEPTION_AT_END();
580 }
581
582 DEFINE_STUB_FUNCTION(JSObject*, op_put_by_id_transition_realloc)
583 {
584     STUB_INIT_STACK_FRAME(stackFrame);
585
586     JSValue baseValue = stackFrame.args[0].jsValue();
587     int32_t oldSize = stackFrame.args[3].int32();
588     Structure* newStructure = stackFrame.args[4].structure();
589     int32_t newSize = newStructure->outOfLineCapacity();
590     
591     ASSERT(oldSize >= 0);
592     ASSERT(newSize > oldSize);
593
594     ASSERT(baseValue.isObject());
595     JSObject* base = asObject(baseValue);
596     VM& vm = *stackFrame.vm;
597     Butterfly* butterfly = base->growOutOfLineStorage(vm, oldSize, newSize);
598     base->setButterfly(vm, butterfly, newStructure);
599
600     return base;
601 }
602
603 DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_id)
604 {
605     STUB_INIT_STACK_FRAME(stackFrame);
606     CallFrame* callFrame = stackFrame.callFrame;
607     Identifier& ident = stackFrame.args[1].identifier();
608
609     CodeBlock* codeBlock = stackFrame.callFrame->codeBlock();
610     StructureStubInfo* stubInfo = &codeBlock->getStubInfo(STUB_RETURN_ADDRESS);
611     AccessType accessType = static_cast<AccessType>(stubInfo->accessType);
612
613     JSValue baseValue = stackFrame.args[0].jsValue();
614     PropertySlot slot(baseValue);
615     JSValue result = baseValue.get(callFrame, ident, slot);
616     
617     if (accessType != static_cast<AccessType>(stubInfo->accessType))
618         return JSValue::encode(result);
619
620     if (!stubInfo->seenOnce())
621         stubInfo->setSeen();
622     else
623         tryCacheGetByID(callFrame, codeBlock, STUB_RETURN_ADDRESS, baseValue, ident, slot, stubInfo);
624
625     CHECK_FOR_EXCEPTION_AT_END();
626     return JSValue::encode(result);
627 }
628
629 DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_id_self_fail)
630 {
631     STUB_INIT_STACK_FRAME(stackFrame);
632
633     CallFrame* callFrame = stackFrame.callFrame;
634     Identifier& ident = stackFrame.args[1].identifier();
635
636     CodeBlock* codeBlock = callFrame->codeBlock();
637     StructureStubInfo* stubInfo = &codeBlock->getStubInfo(STUB_RETURN_ADDRESS);
638     AccessType accessType = static_cast<AccessType>(stubInfo->accessType);
639
640     JSValue baseValue = stackFrame.args[0].jsValue();
641     PropertySlot slot(baseValue);
642     JSValue result = baseValue.get(callFrame, ident, slot);
643     
644     if (accessType != static_cast<AccessType>(stubInfo->accessType))
645         return JSValue::encode(result);
646
647     CHECK_FOR_EXCEPTION();
648
649     ConcurrentJITLocker locker(codeBlock->m_lock);
650     
651     if (baseValue.isCell()
652         && slot.isCacheable()
653         && !baseValue.asCell()->structure()->isUncacheableDictionary()
654         && slot.slotBase() == baseValue) {
655
656         PolymorphicAccessStructureList* polymorphicStructureList;
657         int listIndex = 1;
658
659         if (stubInfo->accessType == access_unset)
660             stubInfo->initGetByIdSelf(callFrame->vm(), codeBlock->ownerExecutable(), baseValue.asCell()->structure());
661
662         if (stubInfo->accessType == access_get_by_id_self) {
663             ASSERT(!stubInfo->stubRoutine);
664             polymorphicStructureList = new PolymorphicAccessStructureList(callFrame->vm(), codeBlock->ownerExecutable(), 0, stubInfo->u.getByIdSelf.baseObjectStructure.get(), true);
665             stubInfo->initGetByIdSelfList(polymorphicStructureList, 1);
666         } else {
667             polymorphicStructureList = stubInfo->u.getByIdSelfList.structureList;
668             listIndex = stubInfo->u.getByIdSelfList.listSize;
669         }
670         if (listIndex < POLYMORPHIC_LIST_CACHE_SIZE) {
671             stubInfo->u.getByIdSelfList.listSize++;
672             JIT::compileGetByIdSelfList(callFrame->scope()->vm(), codeBlock, stubInfo, polymorphicStructureList, listIndex, baseValue.asCell()->structure(), ident, slot, slot.cachedOffset());
673
674             if (listIndex == (POLYMORPHIC_LIST_CACHE_SIZE - 1))
675                 ctiPatchCallByReturnAddress(codeBlock, STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_id_generic));
676         }
677     } else
678         ctiPatchCallByReturnAddress(callFrame->codeBlock(), STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_id_generic));
679     return JSValue::encode(result);
680 }
681
682 static PolymorphicAccessStructureList* getPolymorphicAccessStructureListSlot(VM& vm, ScriptExecutable* owner, StructureStubInfo* stubInfo, int& listIndex)
683 {
684     PolymorphicAccessStructureList* prototypeStructureList = 0;
685     listIndex = 1;
686
687     switch (stubInfo->accessType) {
688     case access_get_by_id_proto:
689         prototypeStructureList = new PolymorphicAccessStructureList(vm, owner, stubInfo->stubRoutine, stubInfo->u.getByIdProto.baseObjectStructure.get(), stubInfo->u.getByIdProto.prototypeStructure.get(), true);
690         stubInfo->stubRoutine.clear();
691         stubInfo->initGetByIdProtoList(prototypeStructureList, 2);
692         break;
693     case access_get_by_id_chain:
694         prototypeStructureList = new PolymorphicAccessStructureList(vm, owner, stubInfo->stubRoutine, stubInfo->u.getByIdChain.baseObjectStructure.get(), stubInfo->u.getByIdChain.chain.get(), true);
695         stubInfo->stubRoutine.clear();
696         stubInfo->initGetByIdProtoList(prototypeStructureList, 2);
697         break;
698     case access_get_by_id_proto_list:
699         prototypeStructureList = stubInfo->u.getByIdProtoList.structureList;
700         listIndex = stubInfo->u.getByIdProtoList.listSize;
701         if (listIndex < POLYMORPHIC_LIST_CACHE_SIZE)
702             stubInfo->u.getByIdProtoList.listSize++;
703         break;
704     default:
705         RELEASE_ASSERT_NOT_REACHED();
706     }
707     
708     ASSERT(listIndex <= POLYMORPHIC_LIST_CACHE_SIZE);
709     return prototypeStructureList;
710 }
711
712 DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_id_getter_stub)
713 {
714     STUB_INIT_STACK_FRAME(stackFrame);
715     CallFrame* callFrame = stackFrame.callFrame;
716     JSValue result = callGetter(callFrame, stackFrame.args[1].jsObject(), stackFrame.args[0].jsObject());
717     if (callFrame->hadException())
718         returnToThrowTrampoline(&callFrame->vm(), stackFrame.args[2].returnAddress(), STUB_RETURN_ADDRESS);
719
720     return JSValue::encode(result);
721 }
722
723 DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_id_custom_stub)
724 {
725     STUB_INIT_STACK_FRAME(stackFrame);
726     CallFrame* callFrame = stackFrame.callFrame;
727     JSObject* slotBase = stackFrame.args[0].jsObject();
728     PropertySlot::GetValueFunc getter = reinterpret_cast<PropertySlot::GetValueFunc>(stackFrame.args[1].asPointer);
729     const Identifier& ident = stackFrame.args[2].identifier();
730     JSValue result = getter(callFrame, slotBase, ident);
731     if (callFrame->hadException())
732         returnToThrowTrampoline(&callFrame->vm(), stackFrame.args[3].returnAddress(), STUB_RETURN_ADDRESS);
733     
734     return JSValue::encode(result);
735 }
736
737 DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_id_proto_list)
738 {
739     STUB_INIT_STACK_FRAME(stackFrame);
740
741     CallFrame* callFrame = stackFrame.callFrame;
742     const Identifier& propertyName = stackFrame.args[1].identifier();
743
744     CodeBlock* codeBlock = callFrame->codeBlock();
745     StructureStubInfo* stubInfo = &codeBlock->getStubInfo(STUB_RETURN_ADDRESS);
746     AccessType accessType = static_cast<AccessType>(stubInfo->accessType);
747
748     JSValue baseValue = stackFrame.args[0].jsValue();
749     PropertySlot slot(baseValue);
750     JSValue result = baseValue.get(callFrame, propertyName, slot);
751
752     CHECK_FOR_EXCEPTION();
753
754     if (accessType != static_cast<AccessType>(stubInfo->accessType)
755         || !baseValue.isCell()
756         || !slot.isCacheable()
757         || baseValue.asCell()->structure()->isDictionary()
758         || baseValue.asCell()->structure()->typeInfo().prohibitsPropertyCaching()) {
759         ctiPatchCallByReturnAddress(callFrame->codeBlock(), STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_id_proto_fail));
760         return JSValue::encode(result);
761     }
762
763     ConcurrentJITLocker locker(codeBlock->m_lock);
764     
765     Structure* structure = baseValue.asCell()->structure();
766
767     JSObject* slotBaseObject = asObject(slot.slotBase());
768     
769     PropertyOffset offset = slot.cachedOffset();
770
771     if (slot.slotBase() == baseValue)
772         ctiPatchCallByReturnAddress(codeBlock, STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_id_proto_fail));
773     else if (slot.slotBase() == baseValue.asCell()->structure()->prototypeForLookup(callFrame)) {
774         ASSERT(!baseValue.asCell()->structure()->isDictionary());
775         
776         if (baseValue.asCell()->structure()->typeInfo().hasImpureGetOwnPropertySlot()) {
777             ctiPatchCallByReturnAddress(codeBlock, STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_id_proto_fail));
778             return JSValue::encode(result);
779         }
780         
781         // Since we're accessing a prototype in a loop, it's a good bet that it
782         // should not be treated as a dictionary.
783         if (slotBaseObject->structure()->isDictionary()) {
784             slotBaseObject->flattenDictionaryObject(callFrame->vm());
785             offset = slotBaseObject->structure()->get(callFrame->vm(), propertyName);
786         }
787
788         int listIndex;
789         PolymorphicAccessStructureList* prototypeStructureList = getPolymorphicAccessStructureListSlot(callFrame->vm(), codeBlock->ownerExecutable(), stubInfo, listIndex);
790         if (listIndex < POLYMORPHIC_LIST_CACHE_SIZE) {
791             JIT::compileGetByIdProtoList(callFrame->scope()->vm(), callFrame, codeBlock, stubInfo, prototypeStructureList, listIndex, structure, slotBaseObject->structure(), propertyName, slot, offset);
792
793             if (listIndex == (POLYMORPHIC_LIST_CACHE_SIZE - 1))
794                 ctiPatchCallByReturnAddress(codeBlock, STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_id_proto_list_full));
795         }
796     } else {
797         size_t count = normalizePrototypeChainForChainAccess(callFrame, baseValue, slot.slotBase(), propertyName, offset);
798         if (count == InvalidPrototypeChain) {
799             ctiPatchCallByReturnAddress(codeBlock, STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_id_proto_fail));
800             return JSValue::encode(result);
801         }
802         
803         ASSERT(!baseValue.asCell()->structure()->isDictionary());
804         int listIndex;
805         PolymorphicAccessStructureList* prototypeStructureList = getPolymorphicAccessStructureListSlot(callFrame->vm(), codeBlock->ownerExecutable(), stubInfo, listIndex);
806         
807         if (listIndex < POLYMORPHIC_LIST_CACHE_SIZE) {
808             StructureChain* protoChain = structure->prototypeChain(callFrame);
809             JIT::compileGetByIdChainList(callFrame->scope()->vm(), callFrame, codeBlock, stubInfo, prototypeStructureList, listIndex, structure, protoChain, count, propertyName, slot, offset);
810
811             if (listIndex == (POLYMORPHIC_LIST_CACHE_SIZE - 1))
812                 ctiPatchCallByReturnAddress(codeBlock, STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_id_proto_list_full));
813         }
814     }
815
816     return JSValue::encode(result);
817 }
818
819 DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_id_proto_list_full)
820 {
821     STUB_INIT_STACK_FRAME(stackFrame);
822
823     JSValue baseValue = stackFrame.args[0].jsValue();
824     PropertySlot slot(baseValue);
825     JSValue result = baseValue.get(stackFrame.callFrame, stackFrame.args[1].identifier(), slot);
826
827     CHECK_FOR_EXCEPTION_AT_END();
828     return JSValue::encode(result);
829 }
830
831 DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_id_proto_fail)
832 {
833     STUB_INIT_STACK_FRAME(stackFrame);
834
835     JSValue baseValue = stackFrame.args[0].jsValue();
836     PropertySlot slot(baseValue);
837     JSValue result = baseValue.get(stackFrame.callFrame, stackFrame.args[1].identifier(), slot);
838
839     CHECK_FOR_EXCEPTION_AT_END();
840     return JSValue::encode(result);
841 }
842
843 DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_id_array_fail)
844 {
845     STUB_INIT_STACK_FRAME(stackFrame);
846
847     JSValue baseValue = stackFrame.args[0].jsValue();
848     PropertySlot slot(baseValue);
849     JSValue result = baseValue.get(stackFrame.callFrame, stackFrame.args[1].identifier(), slot);
850
851     CHECK_FOR_EXCEPTION_AT_END();
852     return JSValue::encode(result);
853 }
854
855 DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_id_string_fail)
856 {
857     STUB_INIT_STACK_FRAME(stackFrame);
858
859     JSValue baseValue = stackFrame.args[0].jsValue();
860     PropertySlot slot(baseValue);
861     JSValue result = baseValue.get(stackFrame.callFrame, stackFrame.args[1].identifier(), slot);
862
863     CHECK_FOR_EXCEPTION_AT_END();
864     return JSValue::encode(result);
865 }
866
867 DEFINE_STUB_FUNCTION(EncodedJSValue, op_check_has_instance)
868 {
869     STUB_INIT_STACK_FRAME(stackFrame);
870
871     CallFrame* callFrame = stackFrame.callFrame;
872     JSValue value = stackFrame.args[0].jsValue();
873     JSValue baseVal = stackFrame.args[1].jsValue();
874
875     if (baseVal.isObject()) {
876         JSObject* baseObject = asObject(baseVal);
877         ASSERT(!baseObject->structure()->typeInfo().implementsDefaultHasInstance());
878         if (baseObject->structure()->typeInfo().implementsHasInstance()) {
879             bool result = baseObject->methodTable()->customHasInstance(baseObject, callFrame, value);
880             CHECK_FOR_EXCEPTION_AT_END();
881             return JSValue::encode(jsBoolean(result));
882         }
883     }
884
885     stackFrame.vm->exception = createInvalidParameterError(callFrame, "instanceof", baseVal);
886     VM_THROW_EXCEPTION_AT_END();
887     return JSValue::encode(JSValue());
888 }
889
890 #if ENABLE(DFG_JIT)
891 DEFINE_STUB_FUNCTION(void, optimize)
892 {
893     STUB_INIT_STACK_FRAME(stackFrame);
894     
895     // Defer GC so that it doesn't run between when we enter into this slow path and
896     // when we figure out the state of our code block. This prevents a number of
897     // awkward reentrancy scenarios, including:
898     //
899     // - The optimized version of our code block being jettisoned by GC right after
900     //   we concluded that we wanted to use it.
901     //
902     // - An optimized version of our code block being installed just as we decided
903     //   that it wasn't ready yet.
904     //
905     // This still leaves the following: anytime we return from cti_optimize, we may
906     // GC, and the GC may either jettison the optimized version of our code block,
907     // or it may install the optimized version of our code block even though we
908     // concluded that it wasn't ready yet.
909     //
910     // Note that jettisoning won't happen if we already initiated OSR, because in
911     // that case we would have already planted the optimized code block into the JS
912     // stack.
913     DeferGC deferGC(stackFrame.vm->heap);
914     
915     CallFrame* callFrame = stackFrame.callFrame;
916     CodeBlock* codeBlock = callFrame->codeBlock();
917     unsigned bytecodeIndex = stackFrame.args[0].int32();
918
919     if (bytecodeIndex) {
920         // If we're attempting to OSR from a loop, assume that this should be
921         // separately optimized.
922         codeBlock->m_shouldAlwaysBeInlined = false;
923     }
924     
925     if (Options::verboseOSR()) {
926         dataLog(
927             *codeBlock, ": Entered optimize with bytecodeIndex = ", bytecodeIndex,
928             ", executeCounter = ", codeBlock->jitExecuteCounter(),
929             ", optimizationDelayCounter = ", codeBlock->reoptimizationRetryCounter(),
930             ", exitCounter = ");
931         if (codeBlock->hasOptimizedReplacement())
932             dataLog(codeBlock->replacement()->osrExitCounter());
933         else
934             dataLog("N/A");
935         dataLog("\n");
936     }
937
938     if (!codeBlock->checkIfOptimizationThresholdReached()) {
939         codeBlock->updateAllPredictions();
940         if (Options::verboseOSR())
941             dataLog("Choosing not to optimize ", *codeBlock, " yet, because the threshold hasn't been reached.\n");
942         return;
943     }
944     
945     if (codeBlock->m_shouldAlwaysBeInlined) {
946         codeBlock->updateAllPredictions();
947         codeBlock->optimizeAfterWarmUp();
948         if (Options::verboseOSR())
949             dataLog("Choosing not to optimize ", *codeBlock, " yet, because m_shouldAlwaysBeInlined == true.\n");
950         return;
951     }
952     
953     // We cannot be in the process of asynchronous compilation and also have an optimized
954     // replacement.
955     ASSERT(
956         !stackFrame.vm->worklist
957         || !(stackFrame.vm->worklist->compilationState(codeBlock) != DFG::Worklist::NotKnown
958              && codeBlock->hasOptimizedReplacement()));
959     
960     DFG::Worklist::State worklistState;
961     if (stackFrame.vm->worklist) {
962         // The call to DFG::Worklist::completeAllReadyPlansForVM() will complete all ready
963         // (i.e. compiled) code blocks. But if it completes ours, we also need to know
964         // what the result was so that we don't plow ahead and attempt OSR or immediate
965         // reoptimization. This will have already also set the appropriate JIT execution
966         // count threshold depending on what happened, so if the compilation was anything
967         // but successful we just want to return early. See the case for worklistState ==
968         // DFG::Worklist::Compiled, below.
969         
970         // Note that we could have alternatively just called Worklist::compilationState()
971         // here, and if it returned Compiled, we could have then called
972         // completeAndScheduleOSR() below. But that would have meant that it could take
973         // longer for code blocks to be completed: they would only complete when *their*
974         // execution count trigger fired; but that could take a while since the firing is
975         // racy. It could also mean that code blocks that never run again after being
976         // compiled would sit on the worklist until next GC. That's fine, but it's
977         // probably a waste of memory. Our goal here is to complete code blocks as soon as
978         // possible in order to minimize the chances of us executing baseline code after
979         // optimized code is already available.
980         
981         worklistState =
982             stackFrame.vm->worklist->completeAllReadyPlansForVM(*stackFrame.vm, codeBlock);
983     } else
984         worklistState = DFG::Worklist::NotKnown;
985     
986     if (worklistState == DFG::Worklist::Compiling) {
987         // We cannot be in the process of asynchronous compilation and also have an optimized
988         // replacement.
989         RELEASE_ASSERT(!codeBlock->hasOptimizedReplacement());
990         codeBlock->setOptimizationThresholdBasedOnCompilationResult(CompilationDeferred);
991         return;
992     }
993     
994     if (worklistState == DFG::Worklist::Compiled) {
995         // If we don't have an optimized replacement but we did just get compiled, then
996         // the compilation failed or was invalidated, in which case the execution count
997         // thresholds have already been set appropriately by
998         // CodeBlock::setOptimizationThresholdBasedOnCompilationResult() and we have
999         // nothing left to do.
1000         if (!codeBlock->hasOptimizedReplacement()) {
1001             codeBlock->updateAllPredictions();
1002             if (Options::verboseOSR())
1003                 dataLog("Code block ", *codeBlock, " was compiled but it doesn't have an optimized replacement.\n");
1004             return;
1005         }
1006     } else if (codeBlock->hasOptimizedReplacement()) {
1007         if (Options::verboseOSR())
1008             dataLog("Considering OSR ", *codeBlock, " -> ", *codeBlock->replacement(), ".\n");
1009         // If we have an optimized replacement, then it must be the case that we entered
1010         // cti_optimize from a loop. That's because is there's an optimized replacement,
1011         // then all calls to this function will be relinked to the replacement and so
1012         // the prologue OSR will never fire.
1013         
1014         // This is an interesting threshold check. Consider that a function OSR exits
1015         // in the middle of a loop, while having a relatively low exit count. The exit
1016         // will reset the execution counter to some target threshold, meaning that this
1017         // code won't be reached until that loop heats up for >=1000 executions. But then
1018         // we do a second check here, to see if we should either reoptimize, or just
1019         // attempt OSR entry. Hence it might even be correct for
1020         // shouldReoptimizeFromLoopNow() to always return true. But we make it do some
1021         // additional checking anyway, to reduce the amount of recompilation thrashing.
1022         if (codeBlock->replacement()->shouldReoptimizeFromLoopNow()) {
1023             if (Options::verboseOSR()) {
1024                 dataLog(
1025                     "Triggering reoptimization of ", *codeBlock,
1026                     "(", *codeBlock->replacement(), ") (in loop).\n");
1027             }
1028             codeBlock->reoptimize();
1029             return;
1030         }
1031     } else {
1032         if (!codeBlock->shouldOptimizeNow()) {
1033             if (Options::verboseOSR()) {
1034                 dataLog(
1035                     "Delaying optimization for ", *codeBlock,
1036                     " because of insufficient profiling.\n");
1037             }
1038             return;
1039         }
1040         
1041         if (Options::verboseOSR())
1042             dataLog("Triggering optimized compilation of ", *codeBlock, "\n");
1043         
1044         JSScope* scope = callFrame->scope();
1045         CompilationResult result;
1046         JSObject* error = codeBlock->compileOptimized(callFrame, scope, result, bytecodeIndex);
1047         if (Options::verboseOSR()) {
1048             dataLog("Optimizing compilation of ", *codeBlock, " result: ", result, "\n");
1049             if (error)
1050                 dataLog("WARNING: optimized compilation failed with a JS error.\n");
1051         }
1052         
1053         codeBlock->setOptimizationThresholdBasedOnCompilationResult(result);
1054         if (result != CompilationSuccessful)
1055             return;
1056     }
1057     
1058     CodeBlock* optimizedCodeBlock = codeBlock->replacement();
1059     ASSERT(JITCode::isOptimizingJIT(optimizedCodeBlock->jitType()));
1060     
1061     if (optimizedCodeBlock->jitType() == JITCode::FTLJIT) {
1062         // FTL JIT doesn't support OSR entry yet.
1063         // https://bugs.webkit.org/show_bug.cgi?id=113625
1064         
1065         // Don't attempt OSR entry again.
1066         codeBlock->dontOptimizeAnytimeSoon();
1067         return;
1068     }
1069     
1070     if (void* address = DFG::prepareOSREntry(callFrame, optimizedCodeBlock, bytecodeIndex)) {
1071         if (Options::verboseOSR()) {
1072             dataLog(
1073                 "Performing OSR ", *codeBlock, " -> ", *optimizedCodeBlock, ", address ",
1074                 RawPointer((STUB_RETURN_ADDRESS).value()), " -> ", RawPointer(address), ".\n");
1075         }
1076
1077         codeBlock->optimizeSoon();
1078         STUB_SET_RETURN_ADDRESS(address);
1079         return;
1080     }
1081
1082     if (Options::verboseOSR()) {
1083         dataLog(
1084             "Optimizing ", *codeBlock, " -> ", *codeBlock->replacement(),
1085             " succeeded, OSR failed, after a delay of ",
1086             codeBlock->optimizationDelayCounter(), ".\n");
1087     }
1088
1089     // Count the OSR failure as a speculation failure. If this happens a lot, then
1090     // reoptimize.
1091     optimizedCodeBlock->countOSRExit();
1092     
1093     // We are a lot more conservative about triggering reoptimization after OSR failure than
1094     // before it. If we enter the optimize_from_loop trigger with a bucket full of fail
1095     // already, then we really would like to reoptimize immediately. But this case covers
1096     // something else: there weren't many (or any) speculation failures before, but we just
1097     // failed to enter the speculative code because some variable had the wrong value or
1098     // because the OSR code decided for any spurious reason that it did not want to OSR
1099     // right now. So, we only trigger reoptimization only upon the more conservative (non-loop)
1100     // reoptimization trigger.
1101     if (optimizedCodeBlock->shouldReoptimizeNow()) {
1102         if (Options::verboseOSR()) {
1103             dataLog(
1104                 "Triggering reoptimization of ", *codeBlock, " -> ",
1105                 *codeBlock->replacement(), " (after OSR fail).\n");
1106         }
1107         codeBlock->reoptimize();
1108         return;
1109     }
1110
1111     // OSR failed this time, but it might succeed next time! Let the code run a bit
1112     // longer and then try again.
1113     codeBlock->optimizeAfterWarmUp();
1114 }
1115 #endif // ENABLE(DFG_JIT)
1116
1117 DEFINE_STUB_FUNCTION(EncodedJSValue, op_instanceof)
1118 {
1119     STUB_INIT_STACK_FRAME(stackFrame);
1120
1121     CallFrame* callFrame = stackFrame.callFrame;
1122     JSValue value = stackFrame.args[0].jsValue();
1123     JSValue proto = stackFrame.args[1].jsValue();
1124     
1125     ASSERT(!value.isObject() || !proto.isObject());
1126
1127     bool result = JSObject::defaultHasInstance(callFrame, value, proto);
1128     CHECK_FOR_EXCEPTION_AT_END();
1129     return JSValue::encode(jsBoolean(result));
1130 }
1131
1132 DEFINE_STUB_FUNCTION(EncodedJSValue, op_del_by_id)
1133 {
1134     STUB_INIT_STACK_FRAME(stackFrame);
1135
1136     CallFrame* callFrame = stackFrame.callFrame;
1137     
1138     JSObject* baseObj = stackFrame.args[0].jsValue().toObject(callFrame);
1139
1140     bool couldDelete = baseObj->methodTable()->deleteProperty(baseObj, callFrame, stackFrame.args[1].identifier());
1141     JSValue result = jsBoolean(couldDelete);
1142     if (!couldDelete && callFrame->codeBlock()->isStrictMode())
1143         stackFrame.vm->exception = createTypeError(stackFrame.callFrame, "Unable to delete property.");
1144
1145     CHECK_FOR_EXCEPTION_AT_END();
1146     return JSValue::encode(result);
1147 }
1148
1149 DEFINE_STUB_FUNCTION(JSObject*, op_new_func)
1150 {
1151     STUB_INIT_STACK_FRAME(stackFrame);
1152     
1153     ASSERT(stackFrame.callFrame->codeBlock()->codeType() != FunctionCode || !stackFrame.callFrame->codeBlock()->needsFullScopeChain() || stackFrame.callFrame->uncheckedR(stackFrame.callFrame->codeBlock()->activationRegister()).jsValue());
1154     return JSFunction::create(stackFrame.callFrame, stackFrame.args[0].function(), stackFrame.callFrame->scope());
1155 }
1156
1157 inline void* jitCompileFor(CallFrame* callFrame, CodeSpecializationKind kind)
1158 {
1159     // This function is called by cti_op_call_jitCompile() and
1160     // cti_op_construct_jitCompile() JIT glue trampolines to compile the
1161     // callee function that we want to call. Both cti glue trampolines are
1162     // called by JIT'ed code which has pushed a frame and initialized most of
1163     // the frame content except for the codeBlock.
1164     //
1165     // Normally, the prologue of the callee is supposed to set the frame's cb
1166     // pointer to the cb of the callee. But in this case, the callee code does
1167     // not exist yet until it is compiled below. The compilation process will
1168     // allocate memory which may trigger a GC. The GC, in turn, will scan the
1169     // JSStack, and will expect the frame's cb to either be valid or 0. If
1170     // we don't initialize it, the GC will be accessing invalid memory and may
1171     // crash.
1172     //
1173     // Hence, we should nullify it here before proceeding with the compilation.
1174     callFrame->setCodeBlock(0);
1175
1176     JSFunction* function = jsCast<JSFunction*>(callFrame->callee());
1177     ASSERT(!function->isHostFunction());
1178     FunctionExecutable* executable = function->jsExecutable();
1179     JSScope* callDataScopeChain = function->scope();
1180     JSObject* error = executable->compileFor(callFrame, callDataScopeChain, kind);
1181     if (!error)
1182         return function;
1183     callFrame->vm().exception = error;
1184     return 0;
1185 }
1186
1187 DEFINE_STUB_FUNCTION(void*, op_call_jitCompile)
1188 {
1189     STUB_INIT_STACK_FRAME(stackFrame);
1190
1191 #if !ASSERT_DISABLED
1192     CallData callData;
1193     ASSERT(stackFrame.callFrame->callee()->methodTable()->getCallData(stackFrame.callFrame->callee(), callData) == CallTypeJS);
1194 #endif
1195     
1196     CallFrame* callFrame = stackFrame.callFrame;
1197     void* result = jitCompileFor(callFrame, CodeForCall);
1198     if (!result)
1199         return throwExceptionFromOpCall<void*>(stackFrame, callFrame, STUB_RETURN_ADDRESS);
1200
1201     return result;
1202 }
1203
1204 DEFINE_STUB_FUNCTION(void*, op_construct_jitCompile)
1205 {
1206     STUB_INIT_STACK_FRAME(stackFrame);
1207
1208 #if !ASSERT_DISABLED
1209     ConstructData constructData;
1210     ASSERT(jsCast<JSFunction*>(stackFrame.callFrame->callee())->methodTable()->getConstructData(stackFrame.callFrame->callee(), constructData) == ConstructTypeJS);
1211 #endif
1212
1213     CallFrame* callFrame = stackFrame.callFrame;    
1214     void* result = jitCompileFor(callFrame, CodeForConstruct);
1215     if (!result)
1216         return throwExceptionFromOpCall<void*>(stackFrame, callFrame, STUB_RETURN_ADDRESS);
1217
1218     return result;
1219 }
1220
1221 DEFINE_STUB_FUNCTION(int, op_call_arityCheck)
1222 {
1223     STUB_INIT_STACK_FRAME(stackFrame);
1224
1225     CallFrame* callFrame = stackFrame.callFrame;
1226
1227     int missingArgCount = CommonSlowPaths::arityCheckFor(callFrame, stackFrame.stack, CodeForCall);
1228     if (missingArgCount < 0) {
1229         ErrorWithExecFunctor functor = ErrorWithExecFunctor(createStackOverflowError);
1230         return throwExceptionFromOpCall<int>(stackFrame, callFrame, STUB_RETURN_ADDRESS, functor);
1231     }
1232     return missingArgCount;
1233 }
1234
1235 DEFINE_STUB_FUNCTION(int, op_construct_arityCheck)
1236 {
1237     STUB_INIT_STACK_FRAME(stackFrame);
1238
1239     CallFrame* callFrame = stackFrame.callFrame;
1240
1241     int missingArgCount = CommonSlowPaths::arityCheckFor(callFrame, stackFrame.stack, CodeForConstruct);
1242     if (missingArgCount < 0) {
1243         ErrorWithExecFunctor functor = ErrorWithExecFunctor(createStackOverflowError);
1244         return throwExceptionFromOpCall<int>(stackFrame, callFrame, STUB_RETURN_ADDRESS, functor);
1245     }
1246     return missingArgCount;
1247 }
1248
1249 inline void* lazyLinkFor(CallFrame* callFrame, CodeSpecializationKind kind)
1250 {
1251     JSFunction* callee = jsCast<JSFunction*>(callFrame->callee());
1252     ExecutableBase* executable = callee->executable();
1253
1254     MacroAssemblerCodePtr codePtr;
1255     CodeBlock* codeBlock = 0;
1256     CallLinkInfo* callLinkInfo = &callFrame->callerFrame()->codeBlock()->getCallLinkInfo(callFrame->returnPC());
1257
1258     // This function is called by cti_vm_lazyLinkCall() and
1259     // cti_lazyLinkConstruct JIT glue trampolines to link the callee function
1260     // that we want to call. Both cti glue trampolines are called by JIT'ed
1261     // code which has pushed a frame and initialized most of the frame content
1262     // except for the codeBlock.
1263     //
1264     // Normally, the prologue of the callee is supposed to set the frame's cb
1265     // field to the cb of the callee. But in this case, the callee may not
1266     // exist yet, and if not, it will be generated in the compilation below.
1267     // The compilation will allocate memory which may trigger a GC. The GC, in
1268     // turn, will scan the JSStack, and will expect the frame's cb to be valid
1269     // or 0. If we don't initialize it, the GC will be accessing invalid
1270     // memory and may crash.
1271     //
1272     // Hence, we should nullify it here before proceeding with the compilation.
1273     callFrame->setCodeBlock(0);
1274
1275     if (executable->isHostFunction())
1276         codePtr = executable->generatedJITCodeFor(kind)->addressForCall();
1277     else {
1278         FunctionExecutable* functionExecutable = static_cast<FunctionExecutable*>(executable);
1279         if (JSObject* error = functionExecutable->compileFor(callFrame, callee->scope(), kind)) {
1280             callFrame->vm().exception = error;
1281             return 0;
1282         }
1283         codeBlock = &functionExecutable->generatedBytecodeFor(kind);
1284         if (callFrame->argumentCountIncludingThis() < static_cast<size_t>(codeBlock->numParameters())
1285             || callLinkInfo->callType == CallLinkInfo::CallVarargs)
1286             codePtr = functionExecutable->generatedJITCodeWithArityCheckFor(kind);
1287         else
1288             codePtr = functionExecutable->generatedJITCodeFor(kind)->addressForCall();
1289     }
1290     
1291     ConcurrentJITLocker locker(callFrame->callerFrame()->codeBlock()->m_lock);
1292     if (!callLinkInfo->seenOnce())
1293         callLinkInfo->setSeen();
1294     else
1295         JIT::linkFor(callFrame->callerFrame(), callee, callFrame->callerFrame()->codeBlock(), codeBlock, codePtr, callLinkInfo, &callFrame->vm(), kind);
1296
1297     return codePtr.executableAddress();
1298 }
1299
1300 DEFINE_STUB_FUNCTION(void*, vm_lazyLinkCall)
1301 {
1302     STUB_INIT_STACK_FRAME(stackFrame);
1303
1304     CallFrame* callFrame = stackFrame.callFrame;
1305     void* result = lazyLinkFor(callFrame, CodeForCall);
1306     if (!result)
1307         return throwExceptionFromOpCall<void*>(stackFrame, callFrame, STUB_RETURN_ADDRESS);
1308
1309     return result;
1310 }
1311
1312 DEFINE_STUB_FUNCTION(void*, vm_lazyLinkClosureCall)
1313 {
1314     STUB_INIT_STACK_FRAME(stackFrame);
1315
1316     CallFrame* callFrame = stackFrame.callFrame;
1317     
1318     CodeBlock* callerCodeBlock = callFrame->callerFrame()->codeBlock();
1319     VM* vm = callerCodeBlock->vm();
1320     CallLinkInfo* callLinkInfo = &callerCodeBlock->getCallLinkInfo(callFrame->returnPC());
1321     JSFunction* callee = jsCast<JSFunction*>(callFrame->callee());
1322     ExecutableBase* executable = callee->executable();
1323     Structure* structure = callee->structure();
1324     
1325     ASSERT(callLinkInfo->callType == CallLinkInfo::Call);
1326     ASSERT(callLinkInfo->isLinked());
1327     ASSERT(callLinkInfo->callee);
1328     ASSERT(callee != callLinkInfo->callee.get());
1329     
1330     bool shouldLink = false;
1331     CodeBlock* calleeCodeBlock = 0;
1332     MacroAssemblerCodePtr codePtr;
1333     
1334     if (executable == callLinkInfo->callee.get()->executable()
1335         && structure == callLinkInfo->callee.get()->structure()) {
1336         
1337         shouldLink = true;
1338         
1339         ASSERT(executable->hasJITCodeForCall());
1340         codePtr = executable->generatedJITCodeForCall()->addressForCall();
1341         if (!callee->executable()->isHostFunction()) {
1342             calleeCodeBlock = &jsCast<FunctionExecutable*>(executable)->generatedBytecodeForCall();
1343             if (callFrame->argumentCountIncludingThis() < static_cast<size_t>(calleeCodeBlock->numParameters())) {
1344                 shouldLink = false;
1345                 codePtr = executable->generatedJITCodeWithArityCheckFor(CodeForCall);
1346             }
1347         }
1348     } else if (callee->isHostFunction())
1349         codePtr = executable->generatedJITCodeForCall()->addressForCall();
1350     else {
1351         // Need to clear the code block before compilation, because compilation can GC.
1352         callFrame->setCodeBlock(0);
1353         
1354         FunctionExecutable* functionExecutable = jsCast<FunctionExecutable*>(executable);
1355         JSScope* scopeChain = callee->scope();
1356         JSObject* error = functionExecutable->compileFor(callFrame, scopeChain, CodeForCall);
1357         if (error) {
1358             callFrame->vm().exception = error;
1359             return 0;
1360         }
1361         
1362         codePtr = functionExecutable->generatedJITCodeWithArityCheckFor(CodeForCall);
1363     }
1364     
1365     if (shouldLink) {
1366         ASSERT(codePtr);
1367         ConcurrentJITLocker locker(callerCodeBlock->m_lock);
1368         JIT::compileClosureCall(vm, callLinkInfo, callerCodeBlock, calleeCodeBlock, structure, executable, codePtr);
1369         callLinkInfo->hasSeenClosure = true;
1370     } else
1371         JIT::linkSlowCall(callerCodeBlock, callLinkInfo);
1372
1373     return codePtr.executableAddress();
1374 }
1375
1376 DEFINE_STUB_FUNCTION(void*, vm_lazyLinkConstruct)
1377 {
1378     STUB_INIT_STACK_FRAME(stackFrame);
1379
1380     CallFrame* callFrame = stackFrame.callFrame;
1381     void* result = lazyLinkFor(callFrame, CodeForConstruct);
1382     if (!result)
1383         return throwExceptionFromOpCall<void*>(stackFrame, callFrame, STUB_RETURN_ADDRESS);
1384
1385     return result;
1386 }
1387
1388 DEFINE_STUB_FUNCTION(JSObject*, op_push_activation)
1389 {
1390     STUB_INIT_STACK_FRAME(stackFrame);
1391
1392     JSActivation* activation = JSActivation::create(stackFrame.callFrame->vm(), stackFrame.callFrame, stackFrame.callFrame->codeBlock());
1393     stackFrame.callFrame->setScope(activation);
1394     return activation;
1395 }
1396
1397 DEFINE_STUB_FUNCTION(EncodedJSValue, op_call_NotJSFunction)
1398 {
1399     STUB_INIT_STACK_FRAME(stackFrame);
1400
1401     CallFrame* callFrame = stackFrame.callFrame;
1402     
1403     JSValue callee = callFrame->calleeAsValue();
1404
1405     CallData callData;
1406     CallType callType = getCallData(callee, callData);
1407
1408     ASSERT(callType != CallTypeJS);
1409     if (callType != CallTypeHost) {
1410         ASSERT(callType == CallTypeNone);
1411         ErrorWithExecAndCalleeFunctor functor = ErrorWithExecAndCalleeFunctor(createNotAConstructorError, callee);
1412         return throwExceptionFromOpCall<EncodedJSValue>(stackFrame, callFrame, STUB_RETURN_ADDRESS, functor);
1413     }
1414
1415     EncodedJSValue returnValue;
1416     {
1417         SamplingTool::CallRecord callRecord(CTI_SAMPLER, true);
1418         returnValue = callData.native.function(callFrame);
1419     }
1420
1421     if (stackFrame.vm->exception)
1422         return throwExceptionFromOpCall<EncodedJSValue>(stackFrame, callFrame, STUB_RETURN_ADDRESS);
1423
1424     return returnValue;
1425 }
1426
1427 DEFINE_STUB_FUNCTION(EncodedJSValue, op_create_arguments)
1428 {
1429     STUB_INIT_STACK_FRAME(stackFrame);
1430
1431     Arguments* arguments = Arguments::create(*stackFrame.vm, stackFrame.callFrame);
1432     return JSValue::encode(JSValue(arguments));
1433 }
1434
1435 DEFINE_STUB_FUNCTION(void, op_tear_off_activation)
1436 {
1437     STUB_INIT_STACK_FRAME(stackFrame);
1438
1439     ASSERT(stackFrame.callFrame->codeBlock()->needsFullScopeChain());
1440     jsCast<JSActivation*>(stackFrame.args[0].jsValue())->tearOff(*stackFrame.vm);
1441 }
1442
1443 DEFINE_STUB_FUNCTION(void, op_tear_off_arguments)
1444 {
1445     STUB_INIT_STACK_FRAME(stackFrame);
1446
1447     CallFrame* callFrame = stackFrame.callFrame;
1448     ASSERT(callFrame->codeBlock()->usesArguments());
1449     Arguments* arguments = jsCast<Arguments*>(stackFrame.args[0].jsValue());
1450     if (JSValue activationValue = stackFrame.args[1].jsValue()) {
1451         arguments->didTearOffActivation(callFrame, jsCast<JSActivation*>(activationValue));
1452         return;
1453     }
1454     arguments->tearOff(callFrame);
1455 }
1456
1457 DEFINE_STUB_FUNCTION(void, op_profile_will_call)
1458 {
1459     STUB_INIT_STACK_FRAME(stackFrame);
1460
1461     if (LegacyProfiler* profiler = stackFrame.vm->enabledProfiler())
1462         profiler->willExecute(stackFrame.callFrame, stackFrame.args[0].jsValue());
1463 }
1464
1465 DEFINE_STUB_FUNCTION(void, op_profile_did_call)
1466 {
1467     STUB_INIT_STACK_FRAME(stackFrame);
1468
1469     if (LegacyProfiler* profiler = stackFrame.vm->enabledProfiler())
1470         profiler->didExecute(stackFrame.callFrame, stackFrame.args[0].jsValue());
1471 }
1472
1473 DEFINE_STUB_FUNCTION(JSObject*, op_new_array)
1474 {
1475     STUB_INIT_STACK_FRAME(stackFrame);
1476
1477     return constructArray(stackFrame.callFrame, stackFrame.args[2].arrayAllocationProfile(), reinterpret_cast<JSValue*>(&stackFrame.callFrame->registers()[stackFrame.args[0].int32()]), stackFrame.args[1].int32());
1478 }
1479
1480 DEFINE_STUB_FUNCTION(JSObject*, op_new_array_with_size)
1481 {
1482     STUB_INIT_STACK_FRAME(stackFrame);
1483     
1484     return constructArrayWithSizeQuirk(stackFrame.callFrame, stackFrame.args[1].arrayAllocationProfile(), stackFrame.callFrame->lexicalGlobalObject(), stackFrame.args[0].jsValue());
1485 }
1486
1487 DEFINE_STUB_FUNCTION(JSObject*, op_new_array_buffer)
1488 {
1489     STUB_INIT_STACK_FRAME(stackFrame);
1490     
1491     return constructArray(stackFrame.callFrame, stackFrame.args[2].arrayAllocationProfile(), stackFrame.callFrame->codeBlock()->constantBuffer(stackFrame.args[0].int32()), stackFrame.args[1].int32());
1492 }
1493
1494 DEFINE_STUB_FUNCTION(EncodedJSValue, op_construct_NotJSConstruct)
1495 {
1496     STUB_INIT_STACK_FRAME(stackFrame);
1497
1498     CallFrame* callFrame = stackFrame.callFrame;
1499     JSValue callee = callFrame->calleeAsValue();
1500
1501     ConstructData constructData;
1502     ConstructType constructType = getConstructData(callee, constructData);
1503
1504     ASSERT(constructType != ConstructTypeJS);
1505     if (constructType != ConstructTypeHost) {
1506         ASSERT(constructType == ConstructTypeNone);
1507         ErrorWithExecAndCalleeFunctor functor = ErrorWithExecAndCalleeFunctor(createNotAConstructorError, callee);
1508         return throwExceptionFromOpCall<EncodedJSValue>(stackFrame, callFrame, STUB_RETURN_ADDRESS, functor);
1509     }
1510
1511     EncodedJSValue returnValue;
1512     {
1513         SamplingTool::CallRecord callRecord(CTI_SAMPLER, true);
1514         returnValue = constructData.native.function(callFrame);
1515     }
1516
1517     if (stackFrame.vm->exception)
1518         return throwExceptionFromOpCall<EncodedJSValue>(stackFrame, callFrame, STUB_RETURN_ADDRESS);
1519
1520     return returnValue;
1521 }
1522
1523 static JSValue getByVal(
1524     CallFrame* callFrame, JSValue baseValue, JSValue subscript, ReturnAddressPtr returnAddress)
1525 {
1526     if (LIKELY(baseValue.isCell() && subscript.isString())) {
1527         if (JSValue result = baseValue.asCell()->fastGetOwnProperty(callFrame, asString(subscript)->value(callFrame)))
1528             return result;
1529     }
1530
1531     if (subscript.isUInt32()) {
1532         uint32_t i = subscript.asUInt32();
1533         if (isJSString(baseValue) && asString(baseValue)->canGetIndex(i)) {
1534             ctiPatchCallByReturnAddress(callFrame->codeBlock(), returnAddress, FunctionPtr(cti_op_get_by_val_string));
1535             return asString(baseValue)->getIndex(callFrame, i);
1536         }
1537         return baseValue.get(callFrame, i);
1538     }
1539
1540     if (isName(subscript))
1541         return baseValue.get(callFrame, jsCast<NameInstance*>(subscript.asCell())->privateName());
1542
1543     Identifier property(callFrame, subscript.toString(callFrame)->value(callFrame));
1544     return baseValue.get(callFrame, property);
1545 }
1546
1547 DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_val)
1548 {
1549     STUB_INIT_STACK_FRAME(stackFrame);
1550
1551     CallFrame* callFrame = stackFrame.callFrame;
1552
1553     JSValue baseValue = stackFrame.args[0].jsValue();
1554     JSValue subscript = stackFrame.args[1].jsValue();
1555     
1556     if (baseValue.isObject() && subscript.isInt32()) {
1557         // See if it's worth optimizing this at all.
1558         JSObject* object = asObject(baseValue);
1559         bool didOptimize = false;
1560
1561         unsigned bytecodeOffset = callFrame->locationAsBytecodeOffset();
1562         ASSERT(bytecodeOffset);
1563         ByValInfo& byValInfo = callFrame->codeBlock()->getByValInfo(bytecodeOffset - 1);
1564         ASSERT(!byValInfo.stubRoutine);
1565         
1566         if (hasOptimizableIndexing(object->structure())) {
1567             // Attempt to optimize.
1568             JITArrayMode arrayMode = jitArrayModeForStructure(object->structure());
1569             if (arrayMode != byValInfo.arrayMode) {
1570                 JIT::compileGetByVal(&callFrame->vm(), callFrame->codeBlock(), &byValInfo, STUB_RETURN_ADDRESS, arrayMode);
1571                 didOptimize = true;
1572             }
1573         }
1574         
1575         if (!didOptimize) {
1576             // If we take slow path more than 10 times without patching then make sure we
1577             // never make that mistake again. Or, if we failed to patch and we have some object
1578             // that intercepts indexed get, then don't even wait until 10 times. For cases
1579             // where we see non-index-intercepting objects, this gives 10 iterations worth of
1580             // opportunity for us to observe that the get_by_val may be polymorphic.
1581             if (++byValInfo.slowPathCount >= 10
1582                 || object->structure()->typeInfo().interceptsGetOwnPropertySlotByIndexEvenWhenLengthIsNotZero()) {
1583                 // Don't ever try to optimize.
1584                 RepatchBuffer repatchBuffer(callFrame->codeBlock());
1585                 repatchBuffer.relinkCallerToFunction(STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_val_generic));
1586             }
1587         }
1588     }
1589     
1590     JSValue result = getByVal(callFrame, baseValue, subscript, STUB_RETURN_ADDRESS);
1591     CHECK_FOR_EXCEPTION();
1592     return JSValue::encode(result);
1593 }
1594     
1595 DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_val_generic)
1596 {
1597     STUB_INIT_STACK_FRAME(stackFrame);
1598
1599     CallFrame* callFrame = stackFrame.callFrame;
1600
1601     JSValue baseValue = stackFrame.args[0].jsValue();
1602     JSValue subscript = stackFrame.args[1].jsValue();
1603     
1604     JSValue result = getByVal(callFrame, baseValue, subscript, STUB_RETURN_ADDRESS);
1605     CHECK_FOR_EXCEPTION();
1606     return JSValue::encode(result);
1607 }
1608     
1609 DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_val_string)
1610 {
1611     STUB_INIT_STACK_FRAME(stackFrame);
1612     
1613     CallFrame* callFrame = stackFrame.callFrame;
1614     
1615     JSValue baseValue = stackFrame.args[0].jsValue();
1616     JSValue subscript = stackFrame.args[1].jsValue();
1617     
1618     JSValue result;
1619     
1620     if (LIKELY(subscript.isUInt32())) {
1621         uint32_t i = subscript.asUInt32();
1622         if (isJSString(baseValue) && asString(baseValue)->canGetIndex(i))
1623             result = asString(baseValue)->getIndex(callFrame, i);
1624         else {
1625             result = baseValue.get(callFrame, i);
1626             if (!isJSString(baseValue))
1627                 ctiPatchCallByReturnAddress(callFrame->codeBlock(), STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_val));
1628         }
1629     } else if (isName(subscript))
1630         result = baseValue.get(callFrame, jsCast<NameInstance*>(subscript.asCell())->privateName());
1631     else {
1632         Identifier property(callFrame, subscript.toString(callFrame)->value(callFrame));
1633         result = baseValue.get(callFrame, property);
1634     }
1635     
1636     CHECK_FOR_EXCEPTION_AT_END();
1637     return JSValue::encode(result);
1638 }
1639
1640 static void putByVal(CallFrame* callFrame, JSValue baseValue, JSValue subscript, JSValue value)
1641 {
1642     if (LIKELY(subscript.isUInt32())) {
1643         uint32_t i = subscript.asUInt32();
1644         if (baseValue.isObject()) {
1645             JSObject* object = asObject(baseValue);
1646             if (object->canSetIndexQuickly(i))
1647                 object->setIndexQuickly(callFrame->vm(), i, value);
1648             else
1649                 object->methodTable()->putByIndex(object, callFrame, i, value, callFrame->codeBlock()->isStrictMode());
1650         } else
1651             baseValue.putByIndex(callFrame, i, value, callFrame->codeBlock()->isStrictMode());
1652     } else if (isName(subscript)) {
1653         PutPropertySlot slot(callFrame->codeBlock()->isStrictMode());
1654         baseValue.put(callFrame, jsCast<NameInstance*>(subscript.asCell())->privateName(), value, slot);
1655     } else {
1656         Identifier property(callFrame, subscript.toString(callFrame)->value(callFrame));
1657         if (!callFrame->vm().exception) { // Don't put to an object if toString threw an exception.
1658             PutPropertySlot slot(callFrame->codeBlock()->isStrictMode());
1659             baseValue.put(callFrame, property, value, slot);
1660         }
1661     }
1662 }
1663
1664 DEFINE_STUB_FUNCTION(void, op_put_by_val)
1665 {
1666     STUB_INIT_STACK_FRAME(stackFrame);
1667
1668     CallFrame* callFrame = stackFrame.callFrame;
1669
1670     JSValue baseValue = stackFrame.args[0].jsValue();
1671     JSValue subscript = stackFrame.args[1].jsValue();
1672     JSValue value = stackFrame.args[2].jsValue();
1673     
1674     if (baseValue.isObject() && subscript.isInt32()) {
1675         // See if it's worth optimizing at all.
1676         JSObject* object = asObject(baseValue);
1677         bool didOptimize = false;
1678
1679         unsigned bytecodeOffset = callFrame->locationAsBytecodeOffset();
1680         ASSERT(bytecodeOffset);
1681         ByValInfo& byValInfo = callFrame->codeBlock()->getByValInfo(bytecodeOffset - 1);
1682         ASSERT(!byValInfo.stubRoutine);
1683         
1684         if (hasOptimizableIndexing(object->structure())) {
1685             // Attempt to optimize.
1686             JITArrayMode arrayMode = jitArrayModeForStructure(object->structure());
1687             if (arrayMode != byValInfo.arrayMode) {
1688                 JIT::compilePutByVal(&callFrame->vm(), callFrame->codeBlock(), &byValInfo, STUB_RETURN_ADDRESS, arrayMode);
1689                 didOptimize = true;
1690             }
1691         }
1692
1693         if (!didOptimize) {
1694             // If we take slow path more than 10 times without patching then make sure we
1695             // never make that mistake again. Or, if we failed to patch and we have some object
1696             // that intercepts indexed get, then don't even wait until 10 times. For cases
1697             // where we see non-index-intercepting objects, this gives 10 iterations worth of
1698             // opportunity for us to observe that the get_by_val may be polymorphic.
1699             if (++byValInfo.slowPathCount >= 10
1700                 || object->structure()->typeInfo().interceptsGetOwnPropertySlotByIndexEvenWhenLengthIsNotZero()) {
1701                 // Don't ever try to optimize.
1702                 RepatchBuffer repatchBuffer(callFrame->codeBlock());
1703                 repatchBuffer.relinkCallerToFunction(STUB_RETURN_ADDRESS, FunctionPtr(cti_op_put_by_val_generic));
1704             }
1705         }
1706     }
1707     
1708     putByVal(callFrame, baseValue, subscript, value);
1709
1710     CHECK_FOR_EXCEPTION_AT_END();
1711 }
1712
1713 DEFINE_STUB_FUNCTION(void, op_put_by_val_generic)
1714 {
1715     STUB_INIT_STACK_FRAME(stackFrame);
1716
1717     CallFrame* callFrame = stackFrame.callFrame;
1718
1719     JSValue baseValue = stackFrame.args[0].jsValue();
1720     JSValue subscript = stackFrame.args[1].jsValue();
1721     JSValue value = stackFrame.args[2].jsValue();
1722     
1723     putByVal(callFrame, baseValue, subscript, value);
1724
1725     CHECK_FOR_EXCEPTION_AT_END();
1726 }
1727
1728 DEFINE_STUB_FUNCTION(void*, op_load_varargs)
1729 {
1730     STUB_INIT_STACK_FRAME(stackFrame);
1731
1732     CallFrame* callFrame = stackFrame.callFrame;
1733     JSStack* stack = stackFrame.stack;
1734     JSValue thisValue = stackFrame.args[0].jsValue();
1735     JSValue arguments = stackFrame.args[1].jsValue();
1736     int firstFreeRegister = stackFrame.args[2].int32();
1737
1738     CallFrame* newCallFrame = loadVarargs(callFrame, stack, thisValue, arguments, firstFreeRegister);
1739     if (!newCallFrame)
1740         VM_THROW_EXCEPTION();
1741     return newCallFrame;
1742 }
1743
1744 DEFINE_STUB_FUNCTION(int, op_jless)
1745 {
1746     STUB_INIT_STACK_FRAME(stackFrame);
1747
1748     JSValue src1 = stackFrame.args[0].jsValue();
1749     JSValue src2 = stackFrame.args[1].jsValue();
1750     CallFrame* callFrame = stackFrame.callFrame;
1751
1752     bool result = jsLess<true>(callFrame, src1, src2);
1753     CHECK_FOR_EXCEPTION_AT_END();
1754     return result;
1755 }
1756
1757 DEFINE_STUB_FUNCTION(int, op_jlesseq)
1758 {
1759     STUB_INIT_STACK_FRAME(stackFrame);
1760
1761     JSValue src1 = stackFrame.args[0].jsValue();
1762     JSValue src2 = stackFrame.args[1].jsValue();
1763     CallFrame* callFrame = stackFrame.callFrame;
1764
1765     bool result = jsLessEq<true>(callFrame, src1, src2);
1766     CHECK_FOR_EXCEPTION_AT_END();
1767     return result;
1768 }
1769
1770 DEFINE_STUB_FUNCTION(int, op_jgreater)
1771 {
1772     STUB_INIT_STACK_FRAME(stackFrame);
1773
1774     JSValue src1 = stackFrame.args[0].jsValue();
1775     JSValue src2 = stackFrame.args[1].jsValue();
1776     CallFrame* callFrame = stackFrame.callFrame;
1777
1778     bool result = jsLess<false>(callFrame, src2, src1);
1779     CHECK_FOR_EXCEPTION_AT_END();
1780     return result;
1781 }
1782
1783 DEFINE_STUB_FUNCTION(int, op_jgreatereq)
1784 {
1785     STUB_INIT_STACK_FRAME(stackFrame);
1786
1787     JSValue src1 = stackFrame.args[0].jsValue();
1788     JSValue src2 = stackFrame.args[1].jsValue();
1789     CallFrame* callFrame = stackFrame.callFrame;
1790
1791     bool result = jsLessEq<false>(callFrame, src2, src1);
1792     CHECK_FOR_EXCEPTION_AT_END();
1793     return result;
1794 }
1795
1796 DEFINE_STUB_FUNCTION(int, op_jtrue)
1797 {
1798     STUB_INIT_STACK_FRAME(stackFrame);
1799
1800     JSValue src1 = stackFrame.args[0].jsValue();
1801
1802     bool result = src1.toBoolean(stackFrame.callFrame);
1803     CHECK_FOR_EXCEPTION_AT_END();
1804     return result;
1805 }
1806
1807 DEFINE_STUB_FUNCTION(int, op_eq)
1808 {
1809     STUB_INIT_STACK_FRAME(stackFrame);
1810
1811     JSValue src1 = stackFrame.args[0].jsValue();
1812     JSValue src2 = stackFrame.args[1].jsValue();
1813
1814 #if USE(JSVALUE32_64)
1815     start:
1816     if (src2.isUndefined()) {
1817         return src1.isNull() || 
1818                (src1.isCell() && src1.asCell()->structure()->masqueradesAsUndefined(stackFrame.callFrame->lexicalGlobalObject()))
1819                || src1.isUndefined();
1820     }
1821     
1822     if (src2.isNull()) {
1823         return src1.isUndefined() || 
1824                (src1.isCell() && src1.asCell()->structure()->masqueradesAsUndefined(stackFrame.callFrame->lexicalGlobalObject()))
1825                || src1.isNull();
1826     }
1827
1828     if (src1.isInt32()) {
1829         if (src2.isDouble())
1830             return src1.asInt32() == src2.asDouble();
1831         double d = src2.toNumber(stackFrame.callFrame);
1832         CHECK_FOR_EXCEPTION();
1833         return src1.asInt32() == d;
1834     }
1835
1836     if (src1.isDouble()) {
1837         if (src2.isInt32())
1838             return src1.asDouble() == src2.asInt32();
1839         double d = src2.toNumber(stackFrame.callFrame);
1840         CHECK_FOR_EXCEPTION();
1841         return src1.asDouble() == d;
1842     }
1843
1844     if (src1.isTrue()) {
1845         if (src2.isFalse())
1846             return false;
1847         double d = src2.toNumber(stackFrame.callFrame);
1848         CHECK_FOR_EXCEPTION();
1849         return d == 1.0;
1850     }
1851
1852     if (src1.isFalse()) {
1853         if (src2.isTrue())
1854             return false;
1855         double d = src2.toNumber(stackFrame.callFrame);
1856         CHECK_FOR_EXCEPTION();
1857         return d == 0.0;
1858     }
1859     
1860     if (src1.isUndefined())
1861         return src2.isCell() && src2.asCell()->structure()->masqueradesAsUndefined(stackFrame.callFrame->lexicalGlobalObject());
1862     
1863     if (src1.isNull())
1864         return src2.isCell() && src2.asCell()->structure()->masqueradesAsUndefined(stackFrame.callFrame->lexicalGlobalObject());
1865
1866     JSCell* cell1 = src1.asCell();
1867
1868     if (cell1->isString()) {
1869         if (src2.isInt32())
1870             return jsToNumber(jsCast<JSString*>(cell1)->value(stackFrame.callFrame)) == src2.asInt32();
1871             
1872         if (src2.isDouble())
1873             return jsToNumber(jsCast<JSString*>(cell1)->value(stackFrame.callFrame)) == src2.asDouble();
1874
1875         if (src2.isTrue())
1876             return jsToNumber(jsCast<JSString*>(cell1)->value(stackFrame.callFrame)) == 1.0;
1877
1878         if (src2.isFalse())
1879             return jsToNumber(jsCast<JSString*>(cell1)->value(stackFrame.callFrame)) == 0.0;
1880
1881         JSCell* cell2 = src2.asCell();
1882         if (cell2->isString())
1883             return jsCast<JSString*>(cell1)->value(stackFrame.callFrame) == jsCast<JSString*>(cell2)->value(stackFrame.callFrame);
1884
1885         src2 = asObject(cell2)->toPrimitive(stackFrame.callFrame);
1886         CHECK_FOR_EXCEPTION();
1887         goto start;
1888     }
1889
1890     if (src2.isObject())
1891         return asObject(cell1) == asObject(src2);
1892     src1 = asObject(cell1)->toPrimitive(stackFrame.callFrame);
1893     CHECK_FOR_EXCEPTION();
1894     goto start;
1895     
1896 #else // USE(JSVALUE32_64)
1897     CallFrame* callFrame = stackFrame.callFrame;
1898     
1899     bool result = JSValue::equalSlowCaseInline(callFrame, src1, src2);
1900     CHECK_FOR_EXCEPTION_AT_END();
1901     return result;
1902 #endif // USE(JSVALUE32_64)
1903 }
1904
1905 DEFINE_STUB_FUNCTION(int, op_eq_strings)
1906 {
1907 #if USE(JSVALUE32_64)
1908     STUB_INIT_STACK_FRAME(stackFrame);
1909
1910     JSString* string1 = stackFrame.args[0].jsString();
1911     JSString* string2 = stackFrame.args[1].jsString();
1912
1913     ASSERT(string1->isString());
1914     ASSERT(string2->isString());
1915     return string1->value(stackFrame.callFrame) == string2->value(stackFrame.callFrame);
1916 #else
1917     UNUSED_PARAM(args);
1918     RELEASE_ASSERT_NOT_REACHED();
1919     return 0;
1920 #endif
1921 }
1922
1923 DEFINE_STUB_FUNCTION(JSObject*, op_new_func_exp)
1924 {
1925     STUB_INIT_STACK_FRAME(stackFrame);
1926     CallFrame* callFrame = stackFrame.callFrame;
1927
1928     FunctionExecutable* function = stackFrame.args[0].function();
1929     JSFunction* func = JSFunction::create(callFrame, function, callFrame->scope());
1930     ASSERT(callFrame->codeBlock()->codeType() != FunctionCode || !callFrame->codeBlock()->needsFullScopeChain() || callFrame->uncheckedR(callFrame->codeBlock()->activationRegister()).jsValue());
1931
1932     return func;
1933 }
1934
1935 DEFINE_STUB_FUNCTION(JSObject*, op_new_regexp)
1936 {
1937     STUB_INIT_STACK_FRAME(stackFrame);
1938
1939     CallFrame* callFrame = stackFrame.callFrame;
1940
1941     RegExp* regExp = stackFrame.args[0].regExp();
1942     if (!regExp->isValid()) {
1943         stackFrame.vm->exception = createSyntaxError(callFrame, "Invalid flags supplied to RegExp constructor.");
1944         VM_THROW_EXCEPTION();
1945     }
1946
1947     return RegExpObject::create(*stackFrame.vm, stackFrame.callFrame->lexicalGlobalObject(), stackFrame.callFrame->lexicalGlobalObject()->regExpStructure(), regExp);
1948 }
1949
1950 DEFINE_STUB_FUNCTION(EncodedJSValue, op_call_eval)
1951 {
1952     STUB_INIT_STACK_FRAME(stackFrame);
1953
1954     CallFrame* callFrame = stackFrame.callFrame;
1955     CallFrame* callerFrame = callFrame->callerFrame();
1956     ASSERT(callFrame->callerFrame()->codeBlock()->codeType() != FunctionCode
1957         || !callFrame->callerFrame()->codeBlock()->needsFullScopeChain()
1958         || callFrame->callerFrame()->uncheckedR(callFrame->callerFrame()->codeBlock()->activationRegister()).jsValue());
1959
1960     callFrame->setScope(callerFrame->scope());
1961     callFrame->setReturnPC(static_cast<Instruction*>((STUB_RETURN_ADDRESS).value()));
1962     callFrame->setCodeBlock(0);
1963
1964     if (!isHostFunction(callFrame->calleeAsValue(), globalFuncEval))
1965         return JSValue::encode(JSValue());
1966
1967     JSValue result = eval(callFrame);
1968     if (stackFrame.vm->exception)
1969         return throwExceptionFromOpCall<EncodedJSValue>(stackFrame, callFrame, STUB_RETURN_ADDRESS);
1970
1971     return JSValue::encode(result);
1972 }
1973
1974 DEFINE_STUB_FUNCTION(void*, op_throw)
1975 {
1976     STUB_INIT_STACK_FRAME(stackFrame);
1977     ExceptionHandler handler = jitThrow(stackFrame.vm, stackFrame.callFrame, stackFrame.args[0].jsValue(), STUB_RETURN_ADDRESS);
1978     STUB_SET_RETURN_ADDRESS(handler.catchRoutine);
1979     return handler.callFrame;
1980 }
1981
1982 DEFINE_STUB_FUNCTION(JSPropertyNameIterator*, op_get_pnames)
1983 {
1984     STUB_INIT_STACK_FRAME(stackFrame);
1985
1986     CallFrame* callFrame = stackFrame.callFrame;
1987     JSObject* o = stackFrame.args[0].jsObject();
1988     Structure* structure = o->structure();
1989     JSPropertyNameIterator* jsPropertyNameIterator = structure->enumerationCache();
1990     if (!jsPropertyNameIterator || jsPropertyNameIterator->cachedPrototypeChain() != structure->prototypeChain(callFrame))
1991         jsPropertyNameIterator = JSPropertyNameIterator::create(callFrame, o);
1992     return jsPropertyNameIterator;
1993 }
1994
1995 DEFINE_STUB_FUNCTION(int, has_property)
1996 {
1997     STUB_INIT_STACK_FRAME(stackFrame);
1998
1999     JSObject* base = stackFrame.args[0].jsObject();
2000     JSString* property = stackFrame.args[1].jsString();
2001     int result = base->hasProperty(stackFrame.callFrame, Identifier(stackFrame.callFrame, property->value(stackFrame.callFrame)));
2002     CHECK_FOR_EXCEPTION_AT_END();
2003     return result;
2004 }
2005
2006 DEFINE_STUB_FUNCTION(void, op_push_with_scope)
2007 {
2008     STUB_INIT_STACK_FRAME(stackFrame);
2009
2010     JSObject* o = stackFrame.args[0].jsValue().toObject(stackFrame.callFrame);
2011     CHECK_FOR_EXCEPTION_VOID();
2012     stackFrame.callFrame->setScope(JSWithScope::create(stackFrame.callFrame, o));
2013 }
2014
2015 DEFINE_STUB_FUNCTION(void, op_pop_scope)
2016 {
2017     STUB_INIT_STACK_FRAME(stackFrame);
2018
2019     stackFrame.callFrame->setScope(stackFrame.callFrame->scope()->next());
2020 }
2021
2022 DEFINE_STUB_FUNCTION(void, op_push_name_scope)
2023 {
2024     STUB_INIT_STACK_FRAME(stackFrame);
2025
2026     JSNameScope* scope = JSNameScope::create(stackFrame.callFrame, stackFrame.args[0].identifier(), stackFrame.args[1].jsValue(), stackFrame.args[2].int32());
2027
2028     CallFrame* callFrame = stackFrame.callFrame;
2029     callFrame->setScope(scope);
2030 }
2031
2032 DEFINE_STUB_FUNCTION(void, op_put_by_index)
2033 {
2034     STUB_INIT_STACK_FRAME(stackFrame);
2035
2036     CallFrame* callFrame = stackFrame.callFrame;
2037     unsigned property = stackFrame.args[1].int32();
2038
2039     JSValue arrayValue = stackFrame.args[0].jsValue();
2040     ASSERT(isJSArray(arrayValue));
2041     asArray(arrayValue)->putDirectIndex(callFrame, property, stackFrame.args[2].jsValue());
2042 }
2043
2044 DEFINE_STUB_FUNCTION(void*, op_switch_imm)
2045 {
2046     STUB_INIT_STACK_FRAME(stackFrame);
2047
2048     JSValue scrutinee = stackFrame.args[0].jsValue();
2049     unsigned tableIndex = stackFrame.args[1].int32();
2050     CallFrame* callFrame = stackFrame.callFrame;
2051     CodeBlock* codeBlock = callFrame->codeBlock();
2052
2053     if (scrutinee.isInt32())
2054         return codeBlock->switchJumpTable(tableIndex).ctiForValue(scrutinee.asInt32()).executableAddress();
2055     if (scrutinee.isDouble() && scrutinee.asDouble() == static_cast<int32_t>(scrutinee.asDouble()))
2056         return codeBlock->switchJumpTable(tableIndex).ctiForValue(static_cast<int32_t>(scrutinee.asDouble())).executableAddress();
2057     return codeBlock->switchJumpTable(tableIndex).ctiDefault.executableAddress();
2058 }
2059
2060 DEFINE_STUB_FUNCTION(void*, op_switch_char)
2061 {
2062     STUB_INIT_STACK_FRAME(stackFrame);
2063
2064     JSValue scrutinee = stackFrame.args[0].jsValue();
2065     unsigned tableIndex = stackFrame.args[1].int32();
2066     CallFrame* callFrame = stackFrame.callFrame;
2067     CodeBlock* codeBlock = callFrame->codeBlock();
2068
2069     void* result = codeBlock->switchJumpTable(tableIndex).ctiDefault.executableAddress();
2070
2071     if (scrutinee.isString()) {
2072         StringImpl* value = asString(scrutinee)->value(callFrame).impl();
2073         if (value->length() == 1)
2074             result = codeBlock->switchJumpTable(tableIndex).ctiForValue((*value)[0]).executableAddress();
2075     }
2076
2077     CHECK_FOR_EXCEPTION_AT_END();
2078     return result;
2079 }
2080
2081 DEFINE_STUB_FUNCTION(void*, op_switch_string)
2082 {
2083     STUB_INIT_STACK_FRAME(stackFrame);
2084
2085     JSValue scrutinee = stackFrame.args[0].jsValue();
2086     unsigned tableIndex = stackFrame.args[1].int32();
2087     CallFrame* callFrame = stackFrame.callFrame;
2088     CodeBlock* codeBlock = callFrame->codeBlock();
2089
2090     void* result = codeBlock->stringSwitchJumpTable(tableIndex).ctiDefault.executableAddress();
2091
2092     if (scrutinee.isString()) {
2093         StringImpl* value = asString(scrutinee)->value(callFrame).impl();
2094         result = codeBlock->stringSwitchJumpTable(tableIndex).ctiForValue(value).executableAddress();
2095     }
2096
2097     CHECK_FOR_EXCEPTION_AT_END();
2098     return result;
2099 }
2100
2101 DEFINE_STUB_FUNCTION(void, op_put_getter_setter)
2102 {
2103     STUB_INIT_STACK_FRAME(stackFrame);
2104
2105     CallFrame* callFrame = stackFrame.callFrame;
2106
2107     ASSERT(stackFrame.args[0].jsValue().isObject());
2108     JSObject* baseObj = asObject(stackFrame.args[0].jsValue());
2109
2110     GetterSetter* accessor = GetterSetter::create(callFrame);
2111
2112     JSValue getter = stackFrame.args[2].jsValue();
2113     JSValue setter = stackFrame.args[3].jsValue();
2114     ASSERT(getter.isObject() || getter.isUndefined());
2115     ASSERT(setter.isObject() || setter.isUndefined());
2116     ASSERT(getter.isObject() || setter.isObject());
2117
2118     if (!getter.isUndefined())
2119         accessor->setGetter(callFrame->vm(), asObject(getter));
2120     if (!setter.isUndefined())
2121         accessor->setSetter(callFrame->vm(), asObject(setter));
2122     baseObj->putDirectAccessor(callFrame, stackFrame.args[1].identifier(), accessor, Accessor);
2123 }
2124
2125 DEFINE_STUB_FUNCTION(void, op_throw_static_error)
2126 {
2127     STUB_INIT_STACK_FRAME(stackFrame);
2128
2129     CallFrame* callFrame = stackFrame.callFrame;
2130     String message = errorDescriptionForValue(callFrame, stackFrame.args[0].jsValue())->value(callFrame);
2131     if (stackFrame.args[1].asInt32)
2132         stackFrame.vm->exception = createReferenceError(callFrame, message);
2133     else
2134         stackFrame.vm->exception = createTypeError(callFrame, message);
2135     VM_THROW_EXCEPTION_AT_END();
2136 }
2137
2138 DEFINE_STUB_FUNCTION(void, op_debug)
2139 {
2140     STUB_INIT_STACK_FRAME(stackFrame);
2141
2142     CallFrame* callFrame = stackFrame.callFrame;
2143
2144     int debugHookID = stackFrame.args[0].int32();
2145     int firstLine = stackFrame.args[1].int32();
2146     int lastLine = stackFrame.args[2].int32();
2147     int column = stackFrame.args[3].int32();
2148
2149     stackFrame.vm->interpreter->debug(callFrame, static_cast<DebugHookID>(debugHookID), firstLine, lastLine, column);
2150 }
2151
2152 DEFINE_STUB_FUNCTION(void*, vm_throw)
2153 {
2154     STUB_INIT_STACK_FRAME(stackFrame);
2155     VM* vm = stackFrame.vm;
2156     ExceptionHandler handler = jitThrow(vm, stackFrame.callFrame, vm->exception, vm->exceptionLocation);
2157     STUB_SET_RETURN_ADDRESS(handler.catchRoutine);
2158     return handler.callFrame;
2159 }
2160
2161 #if USE(JSVALUE32_64)
2162 EncodedExceptionHandler JIT_STUB cti_vm_handle_exception(CallFrame* callFrame)
2163 {
2164     ASSERT(!callFrame->hasHostCallFrameFlag());
2165     if (!callFrame) {
2166         // The entire stack has already been unwound. Nothing more to handle.
2167         return encode(uncaughtExceptionHandler());
2168     }
2169
2170     VM* vm = callFrame->codeBlock()->vm();
2171     vm->topCallFrame = callFrame;
2172     return encode(jitThrowNew(vm, callFrame, vm->exception));
2173 }
2174 #else
2175 ExceptionHandler JIT_STUB cti_vm_handle_exception(CallFrame* callFrame)
2176 {
2177     ASSERT(!callFrame->hasHostCallFrameFlag());
2178     if (!callFrame) {
2179         // The entire stack has already been unwound. Nothing more to handle.
2180         return uncaughtExceptionHandler();
2181     }
2182
2183     VM* vm = callFrame->codeBlock()->vm();
2184     vm->topCallFrame = callFrame;
2185     return jitThrowNew(vm, callFrame, vm->exception);
2186 }
2187 #endif
2188
2189 DEFINE_STUB_FUNCTION(EncodedJSValue, to_object)
2190 {
2191     STUB_INIT_STACK_FRAME(stackFrame);
2192
2193     CallFrame* callFrame = stackFrame.callFrame;
2194     return JSValue::encode(stackFrame.args[0].jsValue().toObject(callFrame));
2195 }
2196
2197 DEFINE_STUB_FUNCTION(EncodedJSValue, op_resolve_scope)
2198 {
2199     STUB_INIT_STACK_FRAME(stackFrame);
2200     ExecState* exec = stackFrame.callFrame;
2201     Instruction* pc = stackFrame.args[0].pc();
2202
2203     const Identifier& ident = exec->codeBlock()->identifier(pc[2].u.operand);
2204     return JSValue::encode(JSScope::resolve(exec, exec->scope(), ident));
2205 }
2206
2207 DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_from_scope)
2208 {
2209     STUB_INIT_STACK_FRAME(stackFrame);
2210     ExecState* exec = stackFrame.callFrame;
2211     Instruction* pc = stackFrame.args[0].pc();
2212
2213     const Identifier& ident = exec->codeBlock()->identifier(pc[3].u.operand);
2214     JSObject* scope = jsCast<JSObject*>(exec->uncheckedR(pc[2].u.operand).jsValue());
2215     ResolveModeAndType modeAndType(pc[4].u.operand);
2216
2217     PropertySlot slot(scope);
2218     if (!scope->getPropertySlot(exec, ident, slot)) {
2219         if (modeAndType.mode() == ThrowIfNotFound) {
2220             throwError(exec, createUndefinedVariableError(exec, ident));
2221             VM_THROW_EXCEPTION();
2222         }
2223         return JSValue::encode(jsUndefined());
2224     }
2225
2226     // Covers implicit globals. Since they don't exist until they first execute, we didn't know how to cache them at compile time.
2227     if (slot.isCacheableValue() && slot.slotBase() == scope && scope->structure()->propertyAccessesAreCacheable()) {
2228         if (modeAndType.type() == GlobalProperty || modeAndType.type() == GlobalPropertyWithVarInjectionChecks) {
2229             CodeBlock* codeBlock = exec->codeBlock();
2230             ConcurrentJITLocker locker(codeBlock->m_lock);
2231             pc[5].u.structure.set(exec->vm(), codeBlock->ownerExecutable(), scope->structure());
2232             pc[6].u.operand = slot.cachedOffset();
2233         }
2234     }
2235
2236     return JSValue::encode(slot.getValue(exec, ident));
2237 }
2238
2239 DEFINE_STUB_FUNCTION(void, op_put_to_scope)
2240 {
2241     STUB_INIT_STACK_FRAME(stackFrame);
2242     ExecState* exec = stackFrame.callFrame;
2243     Instruction* pc = stackFrame.args[0].pc();
2244
2245     CodeBlock* codeBlock = exec->codeBlock();
2246     const Identifier& ident = codeBlock->identifier(pc[2].u.operand);
2247     JSObject* scope = jsCast<JSObject*>(exec->uncheckedR(pc[1].u.operand).jsValue());
2248     JSValue value = exec->r(pc[3].u.operand).jsValue();
2249     ResolveModeAndType modeAndType = ResolveModeAndType(pc[4].u.operand);
2250
2251     if (modeAndType.mode() == ThrowIfNotFound && !scope->hasProperty(exec, ident)) {
2252         throwError(exec, createUndefinedVariableError(exec, ident));
2253         VM_THROW_EXCEPTION_AT_END();
2254         return;
2255     }
2256
2257     PutPropertySlot slot(codeBlock->isStrictMode());
2258     scope->methodTable()->put(scope, exec, ident, value, slot);
2259
2260     // Covers implicit globals. Since they don't exist until they first execute, we didn't know how to cache them at compile time.
2261     if (modeAndType.type() == GlobalProperty || modeAndType.type() == GlobalPropertyWithVarInjectionChecks) {
2262         if (slot.isCacheable() && slot.base() == scope && scope->structure()->propertyAccessesAreCacheable()) {
2263             ConcurrentJITLocker locker(codeBlock->m_lock);
2264             pc[5].u.structure.set(exec->vm(), codeBlock->ownerExecutable(), scope->structure());
2265             pc[6].u.operand = slot.cachedOffset();
2266         }
2267     }
2268 }
2269
2270 } // namespace JSC
2271
2272 #endif // ENABLE(JIT)