9af691b09f646a70df643a7553023ea0433ff2fb
[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(
479         stackFrame.callFrame->codeBlock()->isStrictMode(),
480         stackFrame.callFrame->codeBlock()->putByIdContext());
481     stackFrame.args[0].jsValue().put(stackFrame.callFrame, stackFrame.args[1].identifier(), stackFrame.args[2].jsValue(), slot);
482     CHECK_FOR_EXCEPTION_AT_END();
483 }
484
485 DEFINE_STUB_FUNCTION(void, op_put_by_id_direct_generic)
486 {
487     STUB_INIT_STACK_FRAME(stackFrame);
488     
489     PutPropertySlot slot(
490         stackFrame.callFrame->codeBlock()->isStrictMode(),
491         stackFrame.callFrame->codeBlock()->putByIdContext());
492     JSValue baseValue = stackFrame.args[0].jsValue();
493     ASSERT(baseValue.isObject());
494     asObject(baseValue)->putDirect(stackFrame.callFrame->vm(), stackFrame.args[1].identifier(), stackFrame.args[2].jsValue(), slot);
495     CHECK_FOR_EXCEPTION_AT_END();
496 }
497
498 DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_id_generic)
499 {
500     STUB_INIT_STACK_FRAME(stackFrame);
501
502     CallFrame* callFrame = stackFrame.callFrame;
503     Identifier& ident = stackFrame.args[1].identifier();
504
505     JSValue baseValue = stackFrame.args[0].jsValue();
506     PropertySlot slot(baseValue);
507     JSValue result = baseValue.get(callFrame, ident, slot);
508
509     CHECK_FOR_EXCEPTION_AT_END();
510     return JSValue::encode(result);
511 }
512
513 DEFINE_STUB_FUNCTION(void, op_put_by_id)
514 {
515     STUB_INIT_STACK_FRAME(stackFrame);
516     CallFrame* callFrame = stackFrame.callFrame;
517     Identifier& ident = stackFrame.args[1].identifier();
518     
519     CodeBlock* codeBlock = stackFrame.callFrame->codeBlock();
520     StructureStubInfo* stubInfo = &codeBlock->getStubInfo(STUB_RETURN_ADDRESS);
521     AccessType accessType = static_cast<AccessType>(stubInfo->accessType);
522
523     PutPropertySlot slot(
524         callFrame->codeBlock()->isStrictMode(),
525         callFrame->codeBlock()->putByIdContext());
526     stackFrame.args[0].jsValue().put(callFrame, ident, stackFrame.args[2].jsValue(), slot);
527     
528     if (accessType == static_cast<AccessType>(stubInfo->accessType)) {
529         stubInfo->setSeen();
530         tryCachePutByID(callFrame, codeBlock, STUB_RETURN_ADDRESS, stackFrame.args[0].jsValue(), slot, stubInfo, false);
531     }
532     
533     CHECK_FOR_EXCEPTION_AT_END();
534 }
535
536 DEFINE_STUB_FUNCTION(void, op_put_by_id_direct)
537 {
538     STUB_INIT_STACK_FRAME(stackFrame);
539     CallFrame* callFrame = stackFrame.callFrame;
540     Identifier& ident = stackFrame.args[1].identifier();
541     
542     CodeBlock* codeBlock = stackFrame.callFrame->codeBlock();
543     StructureStubInfo* stubInfo = &codeBlock->getStubInfo(STUB_RETURN_ADDRESS);
544     AccessType accessType = static_cast<AccessType>(stubInfo->accessType);
545
546     PutPropertySlot slot(
547         callFrame->codeBlock()->isStrictMode(),
548         callFrame->codeBlock()->putByIdContext());
549     JSValue baseValue = stackFrame.args[0].jsValue();
550     ASSERT(baseValue.isObject());
551     
552     asObject(baseValue)->putDirect(callFrame->vm(), ident, stackFrame.args[2].jsValue(), slot);
553     
554     if (accessType == static_cast<AccessType>(stubInfo->accessType)) {
555         stubInfo->setSeen();
556         tryCachePutByID(callFrame, codeBlock, STUB_RETURN_ADDRESS, stackFrame.args[0].jsValue(), slot, stubInfo, true);
557     }
558     
559     CHECK_FOR_EXCEPTION_AT_END();
560 }
561
562 DEFINE_STUB_FUNCTION(void, op_put_by_id_fail)
563 {
564     STUB_INIT_STACK_FRAME(stackFrame);
565
566     CallFrame* callFrame = stackFrame.callFrame;
567     Identifier& ident = stackFrame.args[1].identifier();
568     
569     PutPropertySlot slot(
570         callFrame->codeBlock()->isStrictMode(),
571         callFrame->codeBlock()->putByIdContext());
572     stackFrame.args[0].jsValue().put(callFrame, ident, stackFrame.args[2].jsValue(), slot);
573
574     CHECK_FOR_EXCEPTION_AT_END();
575 }
576
577 DEFINE_STUB_FUNCTION(void, op_put_by_id_direct_fail)
578 {
579     STUB_INIT_STACK_FRAME(stackFrame);
580     
581     CallFrame* callFrame = stackFrame.callFrame;
582     Identifier& ident = stackFrame.args[1].identifier();
583     
584     PutPropertySlot slot(
585         callFrame->codeBlock()->isStrictMode(),
586         callFrame->codeBlock()->putByIdContext());
587     JSValue baseValue = stackFrame.args[0].jsValue();
588     ASSERT(baseValue.isObject());
589     asObject(baseValue)->putDirect(callFrame->vm(), ident, stackFrame.args[2].jsValue(), slot);
590     
591     CHECK_FOR_EXCEPTION_AT_END();
592 }
593
594 DEFINE_STUB_FUNCTION(JSObject*, op_put_by_id_transition_realloc)
595 {
596     STUB_INIT_STACK_FRAME(stackFrame);
597
598     JSValue baseValue = stackFrame.args[0].jsValue();
599     int32_t oldSize = stackFrame.args[3].int32();
600     Structure* newStructure = stackFrame.args[4].structure();
601     int32_t newSize = newStructure->outOfLineCapacity();
602     
603     ASSERT(oldSize >= 0);
604     ASSERT(newSize > oldSize);
605
606     ASSERT(baseValue.isObject());
607     JSObject* base = asObject(baseValue);
608     VM& vm = *stackFrame.vm;
609     Butterfly* butterfly = base->growOutOfLineStorage(vm, oldSize, newSize);
610     base->setStructureAndButterfly(vm, newStructure, butterfly);
611
612     return base;
613 }
614
615 DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_id)
616 {
617     STUB_INIT_STACK_FRAME(stackFrame);
618     CallFrame* callFrame = stackFrame.callFrame;
619     Identifier& ident = stackFrame.args[1].identifier();
620
621     CodeBlock* codeBlock = stackFrame.callFrame->codeBlock();
622     StructureStubInfo* stubInfo = &codeBlock->getStubInfo(STUB_RETURN_ADDRESS);
623     AccessType accessType = static_cast<AccessType>(stubInfo->accessType);
624
625     JSValue baseValue = stackFrame.args[0].jsValue();
626     PropertySlot slot(baseValue);
627     JSValue result = baseValue.get(callFrame, ident, slot);
628     
629     if (accessType != static_cast<AccessType>(stubInfo->accessType))
630         return JSValue::encode(result);
631
632     if (!stubInfo->seenOnce())
633         stubInfo->setSeen();
634     else
635         tryCacheGetByID(callFrame, codeBlock, STUB_RETURN_ADDRESS, baseValue, ident, slot, stubInfo);
636
637     CHECK_FOR_EXCEPTION_AT_END();
638     return JSValue::encode(result);
639 }
640
641 DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_id_self_fail)
642 {
643     STUB_INIT_STACK_FRAME(stackFrame);
644
645     CallFrame* callFrame = stackFrame.callFrame;
646     Identifier& ident = stackFrame.args[1].identifier();
647
648     CodeBlock* codeBlock = callFrame->codeBlock();
649     StructureStubInfo* stubInfo = &codeBlock->getStubInfo(STUB_RETURN_ADDRESS);
650     AccessType accessType = static_cast<AccessType>(stubInfo->accessType);
651
652     JSValue baseValue = stackFrame.args[0].jsValue();
653     PropertySlot slot(baseValue);
654     JSValue result = baseValue.get(callFrame, ident, slot);
655     
656     if (accessType != static_cast<AccessType>(stubInfo->accessType))
657         return JSValue::encode(result);
658
659     CHECK_FOR_EXCEPTION();
660
661     ConcurrentJITLocker locker(codeBlock->m_lock);
662     
663     if (baseValue.isCell()
664         && slot.isCacheable()
665         && !baseValue.asCell()->structure()->isUncacheableDictionary()
666         && slot.slotBase() == baseValue) {
667
668         PolymorphicAccessStructureList* polymorphicStructureList;
669         int listIndex = 1;
670
671         if (stubInfo->accessType == access_unset)
672             stubInfo->initGetByIdSelf(callFrame->vm(), codeBlock->ownerExecutable(), baseValue.asCell()->structure());
673
674         if (stubInfo->accessType == access_get_by_id_self) {
675             ASSERT(!stubInfo->stubRoutine);
676             polymorphicStructureList = new PolymorphicAccessStructureList(callFrame->vm(), codeBlock->ownerExecutable(), 0, stubInfo->u.getByIdSelf.baseObjectStructure.get(), true);
677             stubInfo->initGetByIdSelfList(polymorphicStructureList, 1);
678         } else {
679             polymorphicStructureList = stubInfo->u.getByIdSelfList.structureList;
680             listIndex = stubInfo->u.getByIdSelfList.listSize;
681         }
682         if (listIndex < POLYMORPHIC_LIST_CACHE_SIZE) {
683             stubInfo->u.getByIdSelfList.listSize++;
684             JIT::compileGetByIdSelfList(callFrame->scope()->vm(), codeBlock, stubInfo, polymorphicStructureList, listIndex, baseValue.asCell()->structure(), ident, slot, slot.cachedOffset());
685
686             if (listIndex == (POLYMORPHIC_LIST_CACHE_SIZE - 1))
687                 ctiPatchCallByReturnAddress(codeBlock, STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_id_generic));
688         }
689     } else
690         ctiPatchCallByReturnAddress(callFrame->codeBlock(), STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_id_generic));
691     return JSValue::encode(result);
692 }
693
694 static PolymorphicAccessStructureList* getPolymorphicAccessStructureListSlot(VM& vm, ScriptExecutable* owner, StructureStubInfo* stubInfo, int& listIndex)
695 {
696     PolymorphicAccessStructureList* prototypeStructureList = 0;
697     listIndex = 1;
698
699     switch (stubInfo->accessType) {
700     case access_get_by_id_proto:
701         prototypeStructureList = new PolymorphicAccessStructureList(vm, owner, stubInfo->stubRoutine, stubInfo->u.getByIdProto.baseObjectStructure.get(), stubInfo->u.getByIdProto.prototypeStructure.get(), true);
702         stubInfo->stubRoutine.clear();
703         stubInfo->initGetByIdProtoList(prototypeStructureList, 2);
704         break;
705     case access_get_by_id_chain:
706         prototypeStructureList = new PolymorphicAccessStructureList(vm, owner, stubInfo->stubRoutine, stubInfo->u.getByIdChain.baseObjectStructure.get(), stubInfo->u.getByIdChain.chain.get(), true);
707         stubInfo->stubRoutine.clear();
708         stubInfo->initGetByIdProtoList(prototypeStructureList, 2);
709         break;
710     case access_get_by_id_proto_list:
711         prototypeStructureList = stubInfo->u.getByIdProtoList.structureList;
712         listIndex = stubInfo->u.getByIdProtoList.listSize;
713         if (listIndex < POLYMORPHIC_LIST_CACHE_SIZE)
714             stubInfo->u.getByIdProtoList.listSize++;
715         break;
716     default:
717         RELEASE_ASSERT_NOT_REACHED();
718     }
719     
720     ASSERT(listIndex <= POLYMORPHIC_LIST_CACHE_SIZE);
721     return prototypeStructureList;
722 }
723
724 DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_id_getter_stub)
725 {
726     STUB_INIT_STACK_FRAME(stackFrame);
727     CallFrame* callFrame = stackFrame.callFrame;
728     JSValue result = callGetter(callFrame, stackFrame.args[1].jsObject(), stackFrame.args[0].jsObject());
729     if (callFrame->hadException())
730         returnToThrowTrampoline(&callFrame->vm(), stackFrame.args[2].returnAddress(), STUB_RETURN_ADDRESS);
731
732     return JSValue::encode(result);
733 }
734
735 DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_id_custom_stub)
736 {
737     STUB_INIT_STACK_FRAME(stackFrame);
738     CallFrame* callFrame = stackFrame.callFrame;
739     JSObject* slotBase = stackFrame.args[0].jsObject();
740     PropertySlot::GetValueFunc getter = reinterpret_cast<PropertySlot::GetValueFunc>(stackFrame.args[1].asPointer);
741     const Identifier& ident = stackFrame.args[2].identifier();
742     JSValue result = getter(callFrame, slotBase, ident);
743     if (callFrame->hadException())
744         returnToThrowTrampoline(&callFrame->vm(), stackFrame.args[3].returnAddress(), STUB_RETURN_ADDRESS);
745     
746     return JSValue::encode(result);
747 }
748
749 DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_id_proto_list)
750 {
751     STUB_INIT_STACK_FRAME(stackFrame);
752
753     CallFrame* callFrame = stackFrame.callFrame;
754     const Identifier& propertyName = stackFrame.args[1].identifier();
755
756     CodeBlock* codeBlock = callFrame->codeBlock();
757     StructureStubInfo* stubInfo = &codeBlock->getStubInfo(STUB_RETURN_ADDRESS);
758     AccessType accessType = static_cast<AccessType>(stubInfo->accessType);
759
760     JSValue baseValue = stackFrame.args[0].jsValue();
761     PropertySlot slot(baseValue);
762     JSValue result = baseValue.get(callFrame, propertyName, slot);
763
764     CHECK_FOR_EXCEPTION();
765
766     if (accessType != static_cast<AccessType>(stubInfo->accessType)
767         || !baseValue.isCell()
768         || !slot.isCacheable()
769         || baseValue.asCell()->structure()->isDictionary()
770         || baseValue.asCell()->structure()->typeInfo().prohibitsPropertyCaching()) {
771         ctiPatchCallByReturnAddress(callFrame->codeBlock(), STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_id_proto_fail));
772         return JSValue::encode(result);
773     }
774
775     ConcurrentJITLocker locker(codeBlock->m_lock);
776     
777     Structure* structure = baseValue.asCell()->structure();
778
779     JSObject* slotBaseObject = asObject(slot.slotBase());
780     
781     PropertyOffset offset = slot.cachedOffset();
782
783     if (slot.slotBase() == baseValue)
784         ctiPatchCallByReturnAddress(codeBlock, STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_id_proto_fail));
785     else if (slot.slotBase() == baseValue.asCell()->structure()->prototypeForLookup(callFrame)) {
786         ASSERT(!baseValue.asCell()->structure()->isDictionary());
787         
788         if (baseValue.asCell()->structure()->typeInfo().hasImpureGetOwnPropertySlot()) {
789             ctiPatchCallByReturnAddress(codeBlock, STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_id_proto_fail));
790             return JSValue::encode(result);
791         }
792         
793         // Since we're accessing a prototype in a loop, it's a good bet that it
794         // should not be treated as a dictionary.
795         if (slotBaseObject->structure()->isDictionary()) {
796             slotBaseObject->flattenDictionaryObject(callFrame->vm());
797             offset = slotBaseObject->structure()->get(callFrame->vm(), propertyName);
798         }
799
800         int listIndex;
801         PolymorphicAccessStructureList* prototypeStructureList = getPolymorphicAccessStructureListSlot(callFrame->vm(), codeBlock->ownerExecutable(), stubInfo, listIndex);
802         if (listIndex < POLYMORPHIC_LIST_CACHE_SIZE) {
803             JIT::compileGetByIdProtoList(callFrame->scope()->vm(), callFrame, codeBlock, stubInfo, prototypeStructureList, listIndex, structure, slotBaseObject->structure(), propertyName, slot, offset);
804
805             if (listIndex == (POLYMORPHIC_LIST_CACHE_SIZE - 1))
806                 ctiPatchCallByReturnAddress(codeBlock, STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_id_proto_list_full));
807         }
808     } else {
809         size_t count = normalizePrototypeChainForChainAccess(callFrame, baseValue, slot.slotBase(), propertyName, offset);
810         if (count == InvalidPrototypeChain) {
811             ctiPatchCallByReturnAddress(codeBlock, STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_id_proto_fail));
812             return JSValue::encode(result);
813         }
814         
815         ASSERT(!baseValue.asCell()->structure()->isDictionary());
816         int listIndex;
817         PolymorphicAccessStructureList* prototypeStructureList = getPolymorphicAccessStructureListSlot(callFrame->vm(), codeBlock->ownerExecutable(), stubInfo, listIndex);
818         
819         if (listIndex < POLYMORPHIC_LIST_CACHE_SIZE) {
820             StructureChain* protoChain = structure->prototypeChain(callFrame);
821             JIT::compileGetByIdChainList(callFrame->scope()->vm(), callFrame, codeBlock, stubInfo, prototypeStructureList, listIndex, structure, protoChain, count, propertyName, slot, offset);
822
823             if (listIndex == (POLYMORPHIC_LIST_CACHE_SIZE - 1))
824                 ctiPatchCallByReturnAddress(codeBlock, STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_id_proto_list_full));
825         }
826     }
827
828     return JSValue::encode(result);
829 }
830
831 DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_id_proto_list_full)
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_proto_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_array_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_get_by_id_string_fail)
868 {
869     STUB_INIT_STACK_FRAME(stackFrame);
870
871     JSValue baseValue = stackFrame.args[0].jsValue();
872     PropertySlot slot(baseValue);
873     JSValue result = baseValue.get(stackFrame.callFrame, stackFrame.args[1].identifier(), slot);
874
875     CHECK_FOR_EXCEPTION_AT_END();
876     return JSValue::encode(result);
877 }
878
879 DEFINE_STUB_FUNCTION(EncodedJSValue, op_check_has_instance)
880 {
881     STUB_INIT_STACK_FRAME(stackFrame);
882
883     CallFrame* callFrame = stackFrame.callFrame;
884     JSValue value = stackFrame.args[0].jsValue();
885     JSValue baseVal = stackFrame.args[1].jsValue();
886
887     if (baseVal.isObject()) {
888         JSObject* baseObject = asObject(baseVal);
889         ASSERT(!baseObject->structure()->typeInfo().implementsDefaultHasInstance());
890         if (baseObject->structure()->typeInfo().implementsHasInstance()) {
891             bool result = baseObject->methodTable()->customHasInstance(baseObject, callFrame, value);
892             CHECK_FOR_EXCEPTION_AT_END();
893             return JSValue::encode(jsBoolean(result));
894         }
895     }
896
897     stackFrame.vm->exception = createInvalidParameterError(callFrame, "instanceof", baseVal);
898     VM_THROW_EXCEPTION_AT_END();
899     return JSValue::encode(JSValue());
900 }
901
902 #if ENABLE(DFG_JIT)
903 DEFINE_STUB_FUNCTION(void, optimize)
904 {
905     STUB_INIT_STACK_FRAME(stackFrame);
906     
907     // Defer GC so that it doesn't run between when we enter into this slow path and
908     // when we figure out the state of our code block. This prevents a number of
909     // awkward reentrancy scenarios, including:
910     //
911     // - The optimized version of our code block being jettisoned by GC right after
912     //   we concluded that we wanted to use it.
913     //
914     // - An optimized version of our code block being installed just as we decided
915     //   that it wasn't ready yet.
916     //
917     // This still leaves the following: anytime we return from cti_optimize, we may
918     // GC, and the GC may either jettison the optimized version of our code block,
919     // or it may install the optimized version of our code block even though we
920     // concluded that it wasn't ready yet.
921     //
922     // Note that jettisoning won't happen if we already initiated OSR, because in
923     // that case we would have already planted the optimized code block into the JS
924     // stack.
925     DeferGC deferGC(stackFrame.vm->heap);
926     
927     CallFrame* callFrame = stackFrame.callFrame;
928     CodeBlock* codeBlock = callFrame->codeBlock();
929     unsigned bytecodeIndex = stackFrame.args[0].int32();
930
931     if (bytecodeIndex) {
932         // If we're attempting to OSR from a loop, assume that this should be
933         // separately optimized.
934         codeBlock->m_shouldAlwaysBeInlined = false;
935     }
936     
937     if (Options::verboseOSR()) {
938         dataLog(
939             *codeBlock, ": Entered optimize with bytecodeIndex = ", bytecodeIndex,
940             ", executeCounter = ", codeBlock->jitExecuteCounter(),
941             ", optimizationDelayCounter = ", codeBlock->reoptimizationRetryCounter(),
942             ", exitCounter = ");
943         if (codeBlock->hasOptimizedReplacement())
944             dataLog(codeBlock->replacement()->osrExitCounter());
945         else
946             dataLog("N/A");
947         dataLog("\n");
948     }
949
950     if (!codeBlock->checkIfOptimizationThresholdReached()) {
951         codeBlock->updateAllPredictions();
952         if (Options::verboseOSR())
953             dataLog("Choosing not to optimize ", *codeBlock, " yet, because the threshold hasn't been reached.\n");
954         return;
955     }
956     
957     if (codeBlock->m_shouldAlwaysBeInlined) {
958         codeBlock->updateAllPredictions();
959         codeBlock->optimizeAfterWarmUp();
960         if (Options::verboseOSR())
961             dataLog("Choosing not to optimize ", *codeBlock, " yet, because m_shouldAlwaysBeInlined == true.\n");
962         return;
963     }
964     
965     // We cannot be in the process of asynchronous compilation and also have an optimized
966     // replacement.
967     ASSERT(
968         !stackFrame.vm->worklist
969         || !(stackFrame.vm->worklist->compilationState(codeBlock) != DFG::Worklist::NotKnown
970              && codeBlock->hasOptimizedReplacement()));
971     
972     DFG::Worklist::State worklistState;
973     if (stackFrame.vm->worklist) {
974         // The call to DFG::Worklist::completeAllReadyPlansForVM() will complete all ready
975         // (i.e. compiled) code blocks. But if it completes ours, we also need to know
976         // what the result was so that we don't plow ahead and attempt OSR or immediate
977         // reoptimization. This will have already also set the appropriate JIT execution
978         // count threshold depending on what happened, so if the compilation was anything
979         // but successful we just want to return early. See the case for worklistState ==
980         // DFG::Worklist::Compiled, below.
981         
982         // Note that we could have alternatively just called Worklist::compilationState()
983         // here, and if it returned Compiled, we could have then called
984         // completeAndScheduleOSR() below. But that would have meant that it could take
985         // longer for code blocks to be completed: they would only complete when *their*
986         // execution count trigger fired; but that could take a while since the firing is
987         // racy. It could also mean that code blocks that never run again after being
988         // compiled would sit on the worklist until next GC. That's fine, but it's
989         // probably a waste of memory. Our goal here is to complete code blocks as soon as
990         // possible in order to minimize the chances of us executing baseline code after
991         // optimized code is already available.
992         
993         worklistState =
994             stackFrame.vm->worklist->completeAllReadyPlansForVM(*stackFrame.vm, codeBlock);
995     } else
996         worklistState = DFG::Worklist::NotKnown;
997     
998     if (worklistState == DFG::Worklist::Compiling) {
999         // We cannot be in the process of asynchronous compilation and also have an optimized
1000         // replacement.
1001         RELEASE_ASSERT(!codeBlock->hasOptimizedReplacement());
1002         codeBlock->setOptimizationThresholdBasedOnCompilationResult(CompilationDeferred);
1003         return;
1004     }
1005     
1006     if (worklistState == DFG::Worklist::Compiled) {
1007         // If we don't have an optimized replacement but we did just get compiled, then
1008         // the compilation failed or was invalidated, in which case the execution count
1009         // thresholds have already been set appropriately by
1010         // CodeBlock::setOptimizationThresholdBasedOnCompilationResult() and we have
1011         // nothing left to do.
1012         if (!codeBlock->hasOptimizedReplacement()) {
1013             codeBlock->updateAllPredictions();
1014             if (Options::verboseOSR())
1015                 dataLog("Code block ", *codeBlock, " was compiled but it doesn't have an optimized replacement.\n");
1016             return;
1017         }
1018     } else if (codeBlock->hasOptimizedReplacement()) {
1019         if (Options::verboseOSR())
1020             dataLog("Considering OSR ", *codeBlock, " -> ", *codeBlock->replacement(), ".\n");
1021         // If we have an optimized replacement, then it must be the case that we entered
1022         // cti_optimize from a loop. That's because is there's an optimized replacement,
1023         // then all calls to this function will be relinked to the replacement and so
1024         // the prologue OSR will never fire.
1025         
1026         // This is an interesting threshold check. Consider that a function OSR exits
1027         // in the middle of a loop, while having a relatively low exit count. The exit
1028         // will reset the execution counter to some target threshold, meaning that this
1029         // code won't be reached until that loop heats up for >=1000 executions. But then
1030         // we do a second check here, to see if we should either reoptimize, or just
1031         // attempt OSR entry. Hence it might even be correct for
1032         // shouldReoptimizeFromLoopNow() to always return true. But we make it do some
1033         // additional checking anyway, to reduce the amount of recompilation thrashing.
1034         if (codeBlock->replacement()->shouldReoptimizeFromLoopNow()) {
1035             if (Options::verboseOSR()) {
1036                 dataLog(
1037                     "Triggering reoptimization of ", *codeBlock,
1038                     "(", *codeBlock->replacement(), ") (in loop).\n");
1039             }
1040             codeBlock->reoptimize();
1041             return;
1042         }
1043     } else {
1044         if (!codeBlock->shouldOptimizeNow()) {
1045             if (Options::verboseOSR()) {
1046                 dataLog(
1047                     "Delaying optimization for ", *codeBlock,
1048                     " because of insufficient profiling.\n");
1049             }
1050             return;
1051         }
1052         
1053         if (Options::verboseOSR())
1054             dataLog("Triggering optimized compilation of ", *codeBlock, "\n");
1055         
1056         JSScope* scope = callFrame->scope();
1057         CompilationResult result;
1058         JSObject* error = codeBlock->compileOptimized(callFrame, scope, result, bytecodeIndex);
1059         if (Options::verboseOSR()) {
1060             dataLog("Optimizing compilation of ", *codeBlock, " result: ", result, "\n");
1061             if (error)
1062                 dataLog("WARNING: optimized compilation failed with a JS error.\n");
1063         }
1064         
1065         codeBlock->setOptimizationThresholdBasedOnCompilationResult(result);
1066         if (result != CompilationSuccessful)
1067             return;
1068     }
1069     
1070     CodeBlock* optimizedCodeBlock = codeBlock->replacement();
1071     ASSERT(JITCode::isOptimizingJIT(optimizedCodeBlock->jitType()));
1072     
1073     if (optimizedCodeBlock->jitType() == JITCode::FTLJIT) {
1074         // FTL JIT doesn't support OSR entry yet.
1075         // https://bugs.webkit.org/show_bug.cgi?id=113625
1076         
1077         // Don't attempt OSR entry again.
1078         codeBlock->dontOptimizeAnytimeSoon();
1079         return;
1080     }
1081     
1082     if (void* address = DFG::prepareOSREntry(callFrame, optimizedCodeBlock, bytecodeIndex)) {
1083         if (Options::verboseOSR()) {
1084             dataLog(
1085                 "Performing OSR ", *codeBlock, " -> ", *optimizedCodeBlock, ", address ",
1086                 RawPointer((STUB_RETURN_ADDRESS).value()), " -> ", RawPointer(address), ".\n");
1087         }
1088
1089         codeBlock->optimizeSoon();
1090         STUB_SET_RETURN_ADDRESS(address);
1091         return;
1092     }
1093
1094     if (Options::verboseOSR()) {
1095         dataLog(
1096             "Optimizing ", *codeBlock, " -> ", *codeBlock->replacement(),
1097             " succeeded, OSR failed, after a delay of ",
1098             codeBlock->optimizationDelayCounter(), ".\n");
1099     }
1100
1101     // Count the OSR failure as a speculation failure. If this happens a lot, then
1102     // reoptimize.
1103     optimizedCodeBlock->countOSRExit();
1104     
1105     // We are a lot more conservative about triggering reoptimization after OSR failure than
1106     // before it. If we enter the optimize_from_loop trigger with a bucket full of fail
1107     // already, then we really would like to reoptimize immediately. But this case covers
1108     // something else: there weren't many (or any) speculation failures before, but we just
1109     // failed to enter the speculative code because some variable had the wrong value or
1110     // because the OSR code decided for any spurious reason that it did not want to OSR
1111     // right now. So, we only trigger reoptimization only upon the more conservative (non-loop)
1112     // reoptimization trigger.
1113     if (optimizedCodeBlock->shouldReoptimizeNow()) {
1114         if (Options::verboseOSR()) {
1115             dataLog(
1116                 "Triggering reoptimization of ", *codeBlock, " -> ",
1117                 *codeBlock->replacement(), " (after OSR fail).\n");
1118         }
1119         codeBlock->reoptimize();
1120         return;
1121     }
1122
1123     // OSR failed this time, but it might succeed next time! Let the code run a bit
1124     // longer and then try again.
1125     codeBlock->optimizeAfterWarmUp();
1126 }
1127 #endif // ENABLE(DFG_JIT)
1128
1129 DEFINE_STUB_FUNCTION(EncodedJSValue, op_instanceof)
1130 {
1131     STUB_INIT_STACK_FRAME(stackFrame);
1132
1133     CallFrame* callFrame = stackFrame.callFrame;
1134     JSValue value = stackFrame.args[0].jsValue();
1135     JSValue proto = stackFrame.args[1].jsValue();
1136     
1137     ASSERT(!value.isObject() || !proto.isObject());
1138
1139     bool result = JSObject::defaultHasInstance(callFrame, value, proto);
1140     CHECK_FOR_EXCEPTION_AT_END();
1141     return JSValue::encode(jsBoolean(result));
1142 }
1143
1144 DEFINE_STUB_FUNCTION(EncodedJSValue, op_del_by_id)
1145 {
1146     STUB_INIT_STACK_FRAME(stackFrame);
1147
1148     CallFrame* callFrame = stackFrame.callFrame;
1149     
1150     JSObject* baseObj = stackFrame.args[0].jsValue().toObject(callFrame);
1151
1152     bool couldDelete = baseObj->methodTable()->deleteProperty(baseObj, callFrame, stackFrame.args[1].identifier());
1153     JSValue result = jsBoolean(couldDelete);
1154     if (!couldDelete && callFrame->codeBlock()->isStrictMode())
1155         stackFrame.vm->exception = createTypeError(stackFrame.callFrame, "Unable to delete property.");
1156
1157     CHECK_FOR_EXCEPTION_AT_END();
1158     return JSValue::encode(result);
1159 }
1160
1161 DEFINE_STUB_FUNCTION(JSObject*, op_new_func)
1162 {
1163     STUB_INIT_STACK_FRAME(stackFrame);
1164     
1165     ASSERT(stackFrame.callFrame->codeBlock()->codeType() != FunctionCode || !stackFrame.callFrame->codeBlock()->needsFullScopeChain() || stackFrame.callFrame->uncheckedR(stackFrame.callFrame->codeBlock()->activationRegister()).jsValue());
1166     return JSFunction::create(stackFrame.callFrame, stackFrame.args[0].function(), stackFrame.callFrame->scope());
1167 }
1168
1169 inline void* jitCompileFor(CallFrame* callFrame, CodeSpecializationKind kind)
1170 {
1171     // This function is called by cti_op_call_jitCompile() and
1172     // cti_op_construct_jitCompile() JIT glue trampolines to compile the
1173     // callee function that we want to call. Both cti glue trampolines are
1174     // called by JIT'ed code which has pushed a frame and initialized most of
1175     // the frame content except for the codeBlock.
1176     //
1177     // Normally, the prologue of the callee is supposed to set the frame's cb
1178     // pointer to the cb of the callee. But in this case, the callee code does
1179     // not exist yet until it is compiled below. The compilation process will
1180     // allocate memory which may trigger a GC. The GC, in turn, will scan the
1181     // JSStack, and will expect the frame's cb to either be valid or 0. If
1182     // we don't initialize it, the GC will be accessing invalid memory and may
1183     // crash.
1184     //
1185     // Hence, we should nullify it here before proceeding with the compilation.
1186     callFrame->setCodeBlock(0);
1187
1188     JSFunction* function = jsCast<JSFunction*>(callFrame->callee());
1189     ASSERT(!function->isHostFunction());
1190     FunctionExecutable* executable = function->jsExecutable();
1191     JSScope* callDataScopeChain = function->scope();
1192     JSObject* error = executable->compileFor(callFrame, callDataScopeChain, kind);
1193     if (!error)
1194         return function;
1195     callFrame->vm().exception = error;
1196     return 0;
1197 }
1198
1199 DEFINE_STUB_FUNCTION(void*, op_call_jitCompile)
1200 {
1201     STUB_INIT_STACK_FRAME(stackFrame);
1202
1203 #if !ASSERT_DISABLED
1204     CallData callData;
1205     ASSERT(stackFrame.callFrame->callee()->methodTable()->getCallData(stackFrame.callFrame->callee(), callData) == CallTypeJS);
1206 #endif
1207     
1208     CallFrame* callFrame = stackFrame.callFrame;
1209     void* result = jitCompileFor(callFrame, CodeForCall);
1210     if (!result)
1211         return throwExceptionFromOpCall<void*>(stackFrame, callFrame, STUB_RETURN_ADDRESS);
1212
1213     return result;
1214 }
1215
1216 DEFINE_STUB_FUNCTION(void*, op_construct_jitCompile)
1217 {
1218     STUB_INIT_STACK_FRAME(stackFrame);
1219
1220 #if !ASSERT_DISABLED
1221     ConstructData constructData;
1222     ASSERT(jsCast<JSFunction*>(stackFrame.callFrame->callee())->methodTable()->getConstructData(stackFrame.callFrame->callee(), constructData) == ConstructTypeJS);
1223 #endif
1224
1225     CallFrame* callFrame = stackFrame.callFrame;    
1226     void* result = jitCompileFor(callFrame, CodeForConstruct);
1227     if (!result)
1228         return throwExceptionFromOpCall<void*>(stackFrame, callFrame, STUB_RETURN_ADDRESS);
1229
1230     return result;
1231 }
1232
1233 DEFINE_STUB_FUNCTION(int, op_call_arityCheck)
1234 {
1235     STUB_INIT_STACK_FRAME(stackFrame);
1236
1237     CallFrame* callFrame = stackFrame.callFrame;
1238
1239     int missingArgCount = CommonSlowPaths::arityCheckFor(callFrame, stackFrame.stack, CodeForCall);
1240     if (missingArgCount < 0) {
1241         ErrorWithExecFunctor functor = ErrorWithExecFunctor(createStackOverflowError);
1242         return throwExceptionFromOpCall<int>(stackFrame, callFrame, STUB_RETURN_ADDRESS, functor);
1243     }
1244     return missingArgCount;
1245 }
1246
1247 DEFINE_STUB_FUNCTION(int, op_construct_arityCheck)
1248 {
1249     STUB_INIT_STACK_FRAME(stackFrame);
1250
1251     CallFrame* callFrame = stackFrame.callFrame;
1252
1253     int missingArgCount = CommonSlowPaths::arityCheckFor(callFrame, stackFrame.stack, CodeForConstruct);
1254     if (missingArgCount < 0) {
1255         ErrorWithExecFunctor functor = ErrorWithExecFunctor(createStackOverflowError);
1256         return throwExceptionFromOpCall<int>(stackFrame, callFrame, STUB_RETURN_ADDRESS, functor);
1257     }
1258     return missingArgCount;
1259 }
1260
1261 inline void* lazyLinkFor(CallFrame* callFrame, CodeSpecializationKind kind)
1262 {
1263     JSFunction* callee = jsCast<JSFunction*>(callFrame->callee());
1264     ExecutableBase* executable = callee->executable();
1265
1266     MacroAssemblerCodePtr codePtr;
1267     CodeBlock* codeBlock = 0;
1268     CallLinkInfo* callLinkInfo = &callFrame->callerFrame()->codeBlock()->getCallLinkInfo(callFrame->returnPC());
1269
1270     // This function is called by cti_vm_lazyLinkCall() and
1271     // cti_lazyLinkConstruct JIT glue trampolines to link the callee function
1272     // that we want to call. Both cti glue trampolines are called by JIT'ed
1273     // code which has pushed a frame and initialized most of the frame content
1274     // except for the codeBlock.
1275     //
1276     // Normally, the prologue of the callee is supposed to set the frame's cb
1277     // field to the cb of the callee. But in this case, the callee may not
1278     // exist yet, and if not, it will be generated in the compilation below.
1279     // The compilation will allocate memory which may trigger a GC. The GC, in
1280     // turn, will scan the JSStack, and will expect the frame's cb to be valid
1281     // or 0. If we don't initialize it, the GC will be accessing invalid
1282     // memory and may crash.
1283     //
1284     // Hence, we should nullify it here before proceeding with the compilation.
1285     callFrame->setCodeBlock(0);
1286
1287     if (executable->isHostFunction())
1288         codePtr = executable->generatedJITCodeFor(kind)->addressForCall();
1289     else {
1290         FunctionExecutable* functionExecutable = static_cast<FunctionExecutable*>(executable);
1291         if (JSObject* error = functionExecutable->compileFor(callFrame, callee->scope(), kind)) {
1292             callFrame->vm().exception = error;
1293             return 0;
1294         }
1295         codeBlock = &functionExecutable->generatedBytecodeFor(kind);
1296         if (callFrame->argumentCountIncludingThis() < static_cast<size_t>(codeBlock->numParameters())
1297             || callLinkInfo->callType == CallLinkInfo::CallVarargs)
1298             codePtr = functionExecutable->generatedJITCodeWithArityCheckFor(kind);
1299         else
1300             codePtr = functionExecutable->generatedJITCodeFor(kind)->addressForCall();
1301     }
1302     
1303     ConcurrentJITLocker locker(callFrame->callerFrame()->codeBlock()->m_lock);
1304     if (!callLinkInfo->seenOnce())
1305         callLinkInfo->setSeen();
1306     else
1307         JIT::linkFor(callFrame->callerFrame(), callee, callFrame->callerFrame()->codeBlock(), codeBlock, codePtr, callLinkInfo, &callFrame->vm(), kind);
1308
1309     return codePtr.executableAddress();
1310 }
1311
1312 DEFINE_STUB_FUNCTION(void*, vm_lazyLinkCall)
1313 {
1314     STUB_INIT_STACK_FRAME(stackFrame);
1315
1316     CallFrame* callFrame = stackFrame.callFrame;
1317     void* result = lazyLinkFor(callFrame, CodeForCall);
1318     if (!result)
1319         return throwExceptionFromOpCall<void*>(stackFrame, callFrame, STUB_RETURN_ADDRESS);
1320
1321     return result;
1322 }
1323
1324 DEFINE_STUB_FUNCTION(void*, vm_lazyLinkClosureCall)
1325 {
1326     STUB_INIT_STACK_FRAME(stackFrame);
1327
1328     CallFrame* callFrame = stackFrame.callFrame;
1329     
1330     CodeBlock* callerCodeBlock = callFrame->callerFrame()->codeBlock();
1331     VM* vm = callerCodeBlock->vm();
1332     CallLinkInfo* callLinkInfo = &callerCodeBlock->getCallLinkInfo(callFrame->returnPC());
1333     JSFunction* callee = jsCast<JSFunction*>(callFrame->callee());
1334     ExecutableBase* executable = callee->executable();
1335     Structure* structure = callee->structure();
1336     
1337     ASSERT(callLinkInfo->callType == CallLinkInfo::Call);
1338     ASSERT(callLinkInfo->isLinked());
1339     ASSERT(callLinkInfo->callee);
1340     ASSERT(callee != callLinkInfo->callee.get());
1341     
1342     bool shouldLink = false;
1343     CodeBlock* calleeCodeBlock = 0;
1344     MacroAssemblerCodePtr codePtr;
1345     
1346     if (executable == callLinkInfo->callee.get()->executable()
1347         && structure == callLinkInfo->callee.get()->structure()) {
1348         
1349         shouldLink = true;
1350         
1351         ASSERT(executable->hasJITCodeForCall());
1352         codePtr = executable->generatedJITCodeForCall()->addressForCall();
1353         if (!callee->executable()->isHostFunction()) {
1354             calleeCodeBlock = &jsCast<FunctionExecutable*>(executable)->generatedBytecodeForCall();
1355             if (callFrame->argumentCountIncludingThis() < static_cast<size_t>(calleeCodeBlock->numParameters())) {
1356                 shouldLink = false;
1357                 codePtr = executable->generatedJITCodeWithArityCheckFor(CodeForCall);
1358             }
1359         }
1360     } else if (callee->isHostFunction())
1361         codePtr = executable->generatedJITCodeForCall()->addressForCall();
1362     else {
1363         // Need to clear the code block before compilation, because compilation can GC.
1364         callFrame->setCodeBlock(0);
1365         
1366         FunctionExecutable* functionExecutable = jsCast<FunctionExecutable*>(executable);
1367         JSScope* scopeChain = callee->scope();
1368         JSObject* error = functionExecutable->compileFor(callFrame, scopeChain, CodeForCall);
1369         if (error) {
1370             callFrame->vm().exception = error;
1371             return 0;
1372         }
1373         
1374         codePtr = functionExecutable->generatedJITCodeWithArityCheckFor(CodeForCall);
1375     }
1376     
1377     if (shouldLink) {
1378         ASSERT(codePtr);
1379         ConcurrentJITLocker locker(callerCodeBlock->m_lock);
1380         JIT::compileClosureCall(vm, callLinkInfo, callerCodeBlock, calleeCodeBlock, structure, executable, codePtr);
1381         callLinkInfo->hasSeenClosure = true;
1382     } else
1383         JIT::linkSlowCall(callerCodeBlock, callLinkInfo);
1384
1385     return codePtr.executableAddress();
1386 }
1387
1388 DEFINE_STUB_FUNCTION(void*, vm_lazyLinkConstruct)
1389 {
1390     STUB_INIT_STACK_FRAME(stackFrame);
1391
1392     CallFrame* callFrame = stackFrame.callFrame;
1393     void* result = lazyLinkFor(callFrame, CodeForConstruct);
1394     if (!result)
1395         return throwExceptionFromOpCall<void*>(stackFrame, callFrame, STUB_RETURN_ADDRESS);
1396
1397     return result;
1398 }
1399
1400 DEFINE_STUB_FUNCTION(JSObject*, op_push_activation)
1401 {
1402     STUB_INIT_STACK_FRAME(stackFrame);
1403
1404     JSActivation* activation = JSActivation::create(stackFrame.callFrame->vm(), stackFrame.callFrame, stackFrame.callFrame->codeBlock());
1405     stackFrame.callFrame->setScope(activation);
1406     return activation;
1407 }
1408
1409 DEFINE_STUB_FUNCTION(EncodedJSValue, op_call_NotJSFunction)
1410 {
1411     STUB_INIT_STACK_FRAME(stackFrame);
1412
1413     CallFrame* callFrame = stackFrame.callFrame;
1414     
1415     JSValue callee = callFrame->calleeAsValue();
1416
1417     CallData callData;
1418     CallType callType = getCallData(callee, callData);
1419
1420     ASSERT(callType != CallTypeJS);
1421     if (callType != CallTypeHost) {
1422         ASSERT(callType == CallTypeNone);
1423         ErrorWithExecAndCalleeFunctor functor = ErrorWithExecAndCalleeFunctor(createNotAFunctionError, callee);
1424         return throwExceptionFromOpCall<EncodedJSValue>(stackFrame, callFrame, STUB_RETURN_ADDRESS, functor);
1425     }
1426
1427     EncodedJSValue returnValue;
1428     {
1429         SamplingTool::CallRecord callRecord(CTI_SAMPLER, true);
1430         returnValue = callData.native.function(callFrame);
1431     }
1432
1433     if (stackFrame.vm->exception)
1434         return throwExceptionFromOpCall<EncodedJSValue>(stackFrame, callFrame, STUB_RETURN_ADDRESS);
1435
1436     return returnValue;
1437 }
1438
1439 DEFINE_STUB_FUNCTION(EncodedJSValue, op_create_arguments)
1440 {
1441     STUB_INIT_STACK_FRAME(stackFrame);
1442
1443     Arguments* arguments = Arguments::create(*stackFrame.vm, stackFrame.callFrame);
1444     return JSValue::encode(JSValue(arguments));
1445 }
1446
1447 DEFINE_STUB_FUNCTION(void, op_tear_off_activation)
1448 {
1449     STUB_INIT_STACK_FRAME(stackFrame);
1450
1451     ASSERT(stackFrame.callFrame->codeBlock()->needsFullScopeChain());
1452     jsCast<JSActivation*>(stackFrame.args[0].jsValue())->tearOff(*stackFrame.vm);
1453 }
1454
1455 DEFINE_STUB_FUNCTION(void, op_tear_off_arguments)
1456 {
1457     STUB_INIT_STACK_FRAME(stackFrame);
1458
1459     CallFrame* callFrame = stackFrame.callFrame;
1460     ASSERT(callFrame->codeBlock()->usesArguments());
1461     Arguments* arguments = jsCast<Arguments*>(stackFrame.args[0].jsValue());
1462     if (JSValue activationValue = stackFrame.args[1].jsValue()) {
1463         arguments->didTearOffActivation(callFrame, jsCast<JSActivation*>(activationValue));
1464         return;
1465     }
1466     arguments->tearOff(callFrame);
1467 }
1468
1469 DEFINE_STUB_FUNCTION(void, op_profile_will_call)
1470 {
1471     STUB_INIT_STACK_FRAME(stackFrame);
1472
1473     if (LegacyProfiler* profiler = stackFrame.vm->enabledProfiler())
1474         profiler->willExecute(stackFrame.callFrame, stackFrame.args[0].jsValue());
1475 }
1476
1477 DEFINE_STUB_FUNCTION(void, op_profile_did_call)
1478 {
1479     STUB_INIT_STACK_FRAME(stackFrame);
1480
1481     if (LegacyProfiler* profiler = stackFrame.vm->enabledProfiler())
1482         profiler->didExecute(stackFrame.callFrame, stackFrame.args[0].jsValue());
1483 }
1484
1485 DEFINE_STUB_FUNCTION(JSObject*, op_new_array)
1486 {
1487     STUB_INIT_STACK_FRAME(stackFrame);
1488
1489     return constructArray(stackFrame.callFrame, stackFrame.args[2].arrayAllocationProfile(), reinterpret_cast<JSValue*>(&stackFrame.callFrame->registers()[stackFrame.args[0].int32()]), stackFrame.args[1].int32());
1490 }
1491
1492 DEFINE_STUB_FUNCTION(JSObject*, op_new_array_with_size)
1493 {
1494     STUB_INIT_STACK_FRAME(stackFrame);
1495     
1496     return constructArrayWithSizeQuirk(stackFrame.callFrame, stackFrame.args[1].arrayAllocationProfile(), stackFrame.callFrame->lexicalGlobalObject(), stackFrame.args[0].jsValue());
1497 }
1498
1499 DEFINE_STUB_FUNCTION(JSObject*, op_new_array_buffer)
1500 {
1501     STUB_INIT_STACK_FRAME(stackFrame);
1502     
1503     return constructArray(stackFrame.callFrame, stackFrame.args[2].arrayAllocationProfile(), stackFrame.callFrame->codeBlock()->constantBuffer(stackFrame.args[0].int32()), stackFrame.args[1].int32());
1504 }
1505
1506 DEFINE_STUB_FUNCTION(EncodedJSValue, op_construct_NotJSConstruct)
1507 {
1508     STUB_INIT_STACK_FRAME(stackFrame);
1509
1510     CallFrame* callFrame = stackFrame.callFrame;
1511     JSValue callee = callFrame->calleeAsValue();
1512
1513     ConstructData constructData;
1514     ConstructType constructType = getConstructData(callee, constructData);
1515
1516     ASSERT(constructType != ConstructTypeJS);
1517     if (constructType != ConstructTypeHost) {
1518         ASSERT(constructType == ConstructTypeNone);
1519         ErrorWithExecAndCalleeFunctor functor = ErrorWithExecAndCalleeFunctor(createNotAConstructorError, callee);
1520         return throwExceptionFromOpCall<EncodedJSValue>(stackFrame, callFrame, STUB_RETURN_ADDRESS, functor);
1521     }
1522
1523     EncodedJSValue returnValue;
1524     {
1525         SamplingTool::CallRecord callRecord(CTI_SAMPLER, true);
1526         returnValue = constructData.native.function(callFrame);
1527     }
1528
1529     if (stackFrame.vm->exception)
1530         return throwExceptionFromOpCall<EncodedJSValue>(stackFrame, callFrame, STUB_RETURN_ADDRESS);
1531
1532     return returnValue;
1533 }
1534
1535 static JSValue getByVal(
1536     CallFrame* callFrame, JSValue baseValue, JSValue subscript, ReturnAddressPtr returnAddress)
1537 {
1538     if (LIKELY(baseValue.isCell() && subscript.isString())) {
1539         if (JSValue result = baseValue.asCell()->fastGetOwnProperty(callFrame, asString(subscript)->value(callFrame)))
1540             return result;
1541     }
1542
1543     if (subscript.isUInt32()) {
1544         uint32_t i = subscript.asUInt32();
1545         if (isJSString(baseValue) && asString(baseValue)->canGetIndex(i)) {
1546             ctiPatchCallByReturnAddress(callFrame->codeBlock(), returnAddress, FunctionPtr(cti_op_get_by_val_string));
1547             return asString(baseValue)->getIndex(callFrame, i);
1548         }
1549         return baseValue.get(callFrame, i);
1550     }
1551
1552     if (isName(subscript))
1553         return baseValue.get(callFrame, jsCast<NameInstance*>(subscript.asCell())->privateName());
1554
1555     Identifier property(callFrame, subscript.toString(callFrame)->value(callFrame));
1556     return baseValue.get(callFrame, property);
1557 }
1558
1559 DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_val)
1560 {
1561     STUB_INIT_STACK_FRAME(stackFrame);
1562
1563     CallFrame* callFrame = stackFrame.callFrame;
1564
1565     JSValue baseValue = stackFrame.args[0].jsValue();
1566     JSValue subscript = stackFrame.args[1].jsValue();
1567     
1568     if (baseValue.isObject() && subscript.isInt32()) {
1569         // See if it's worth optimizing this at all.
1570         JSObject* object = asObject(baseValue);
1571         bool didOptimize = false;
1572
1573         unsigned bytecodeOffset = callFrame->locationAsBytecodeOffset();
1574         ASSERT(bytecodeOffset);
1575         ByValInfo& byValInfo = callFrame->codeBlock()->getByValInfo(bytecodeOffset - 1);
1576         ASSERT(!byValInfo.stubRoutine);
1577         
1578         if (hasOptimizableIndexing(object->structure())) {
1579             // Attempt to optimize.
1580             JITArrayMode arrayMode = jitArrayModeForStructure(object->structure());
1581             if (arrayMode != byValInfo.arrayMode) {
1582                 JIT::compileGetByVal(&callFrame->vm(), callFrame->codeBlock(), &byValInfo, STUB_RETURN_ADDRESS, arrayMode);
1583                 didOptimize = true;
1584             }
1585         }
1586         
1587         if (!didOptimize) {
1588             // If we take slow path more than 10 times without patching then make sure we
1589             // never make that mistake again. Or, if we failed to patch and we have some object
1590             // that intercepts indexed get, then don't even wait until 10 times. For cases
1591             // where we see non-index-intercepting objects, this gives 10 iterations worth of
1592             // opportunity for us to observe that the get_by_val may be polymorphic.
1593             if (++byValInfo.slowPathCount >= 10
1594                 || object->structure()->typeInfo().interceptsGetOwnPropertySlotByIndexEvenWhenLengthIsNotZero()) {
1595                 // Don't ever try to optimize.
1596                 RepatchBuffer repatchBuffer(callFrame->codeBlock());
1597                 repatchBuffer.relinkCallerToFunction(STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_val_generic));
1598             }
1599         }
1600     }
1601     
1602     JSValue result = getByVal(callFrame, baseValue, subscript, STUB_RETURN_ADDRESS);
1603     CHECK_FOR_EXCEPTION();
1604     return JSValue::encode(result);
1605 }
1606     
1607 DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_val_generic)
1608 {
1609     STUB_INIT_STACK_FRAME(stackFrame);
1610
1611     CallFrame* callFrame = stackFrame.callFrame;
1612
1613     JSValue baseValue = stackFrame.args[0].jsValue();
1614     JSValue subscript = stackFrame.args[1].jsValue();
1615     
1616     JSValue result = getByVal(callFrame, baseValue, subscript, STUB_RETURN_ADDRESS);
1617     CHECK_FOR_EXCEPTION();
1618     return JSValue::encode(result);
1619 }
1620     
1621 DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_val_string)
1622 {
1623     STUB_INIT_STACK_FRAME(stackFrame);
1624     
1625     CallFrame* callFrame = stackFrame.callFrame;
1626     
1627     JSValue baseValue = stackFrame.args[0].jsValue();
1628     JSValue subscript = stackFrame.args[1].jsValue();
1629     
1630     JSValue result;
1631     
1632     if (LIKELY(subscript.isUInt32())) {
1633         uint32_t i = subscript.asUInt32();
1634         if (isJSString(baseValue) && asString(baseValue)->canGetIndex(i))
1635             result = asString(baseValue)->getIndex(callFrame, i);
1636         else {
1637             result = baseValue.get(callFrame, i);
1638             if (!isJSString(baseValue))
1639                 ctiPatchCallByReturnAddress(callFrame->codeBlock(), STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_val));
1640         }
1641     } else if (isName(subscript))
1642         result = baseValue.get(callFrame, jsCast<NameInstance*>(subscript.asCell())->privateName());
1643     else {
1644         Identifier property(callFrame, subscript.toString(callFrame)->value(callFrame));
1645         result = baseValue.get(callFrame, property);
1646     }
1647     
1648     CHECK_FOR_EXCEPTION_AT_END();
1649     return JSValue::encode(result);
1650 }
1651
1652 static void putByVal(CallFrame* callFrame, JSValue baseValue, JSValue subscript, JSValue value)
1653 {
1654     if (LIKELY(subscript.isUInt32())) {
1655         uint32_t i = subscript.asUInt32();
1656         if (baseValue.isObject()) {
1657             JSObject* object = asObject(baseValue);
1658             if (object->canSetIndexQuickly(i))
1659                 object->setIndexQuickly(callFrame->vm(), i, value);
1660             else
1661                 object->methodTable()->putByIndex(object, callFrame, i, value, callFrame->codeBlock()->isStrictMode());
1662         } else
1663             baseValue.putByIndex(callFrame, i, value, callFrame->codeBlock()->isStrictMode());
1664     } else if (isName(subscript)) {
1665         PutPropertySlot slot(callFrame->codeBlock()->isStrictMode());
1666         baseValue.put(callFrame, jsCast<NameInstance*>(subscript.asCell())->privateName(), value, slot);
1667     } else {
1668         Identifier property(callFrame, subscript.toString(callFrame)->value(callFrame));
1669         if (!callFrame->vm().exception) { // Don't put to an object if toString threw an exception.
1670             PutPropertySlot slot(callFrame->codeBlock()->isStrictMode());
1671             baseValue.put(callFrame, property, value, slot);
1672         }
1673     }
1674 }
1675
1676 DEFINE_STUB_FUNCTION(void, op_put_by_val)
1677 {
1678     STUB_INIT_STACK_FRAME(stackFrame);
1679
1680     CallFrame* callFrame = stackFrame.callFrame;
1681
1682     JSValue baseValue = stackFrame.args[0].jsValue();
1683     JSValue subscript = stackFrame.args[1].jsValue();
1684     JSValue value = stackFrame.args[2].jsValue();
1685     
1686     if (baseValue.isObject() && subscript.isInt32()) {
1687         // See if it's worth optimizing at all.
1688         JSObject* object = asObject(baseValue);
1689         bool didOptimize = false;
1690
1691         unsigned bytecodeOffset = callFrame->locationAsBytecodeOffset();
1692         ASSERT(bytecodeOffset);
1693         ByValInfo& byValInfo = callFrame->codeBlock()->getByValInfo(bytecodeOffset - 1);
1694         ASSERT(!byValInfo.stubRoutine);
1695         
1696         if (hasOptimizableIndexing(object->structure())) {
1697             // Attempt to optimize.
1698             JITArrayMode arrayMode = jitArrayModeForStructure(object->structure());
1699             if (arrayMode != byValInfo.arrayMode) {
1700                 JIT::compilePutByVal(&callFrame->vm(), callFrame->codeBlock(), &byValInfo, STUB_RETURN_ADDRESS, arrayMode);
1701                 didOptimize = true;
1702             }
1703         }
1704
1705         if (!didOptimize) {
1706             // If we take slow path more than 10 times without patching then make sure we
1707             // never make that mistake again. Or, if we failed to patch and we have some object
1708             // that intercepts indexed get, then don't even wait until 10 times. For cases
1709             // where we see non-index-intercepting objects, this gives 10 iterations worth of
1710             // opportunity for us to observe that the get_by_val may be polymorphic.
1711             if (++byValInfo.slowPathCount >= 10
1712                 || object->structure()->typeInfo().interceptsGetOwnPropertySlotByIndexEvenWhenLengthIsNotZero()) {
1713                 // Don't ever try to optimize.
1714                 RepatchBuffer repatchBuffer(callFrame->codeBlock());
1715                 repatchBuffer.relinkCallerToFunction(STUB_RETURN_ADDRESS, FunctionPtr(cti_op_put_by_val_generic));
1716             }
1717         }
1718     }
1719     
1720     putByVal(callFrame, baseValue, subscript, value);
1721
1722     CHECK_FOR_EXCEPTION_AT_END();
1723 }
1724
1725 DEFINE_STUB_FUNCTION(void, op_put_by_val_generic)
1726 {
1727     STUB_INIT_STACK_FRAME(stackFrame);
1728
1729     CallFrame* callFrame = stackFrame.callFrame;
1730
1731     JSValue baseValue = stackFrame.args[0].jsValue();
1732     JSValue subscript = stackFrame.args[1].jsValue();
1733     JSValue value = stackFrame.args[2].jsValue();
1734     
1735     putByVal(callFrame, baseValue, subscript, value);
1736
1737     CHECK_FOR_EXCEPTION_AT_END();
1738 }
1739
1740 DEFINE_STUB_FUNCTION(void*, op_load_varargs)
1741 {
1742     STUB_INIT_STACK_FRAME(stackFrame);
1743
1744     CallFrame* callFrame = stackFrame.callFrame;
1745     JSStack* stack = stackFrame.stack;
1746     JSValue thisValue = stackFrame.args[0].jsValue();
1747     JSValue arguments = stackFrame.args[1].jsValue();
1748     int firstFreeRegister = stackFrame.args[2].int32();
1749
1750     CallFrame* newCallFrame = loadVarargs(callFrame, stack, thisValue, arguments, firstFreeRegister);
1751     if (!newCallFrame)
1752         VM_THROW_EXCEPTION();
1753     return newCallFrame;
1754 }
1755
1756 DEFINE_STUB_FUNCTION(int, op_jless)
1757 {
1758     STUB_INIT_STACK_FRAME(stackFrame);
1759
1760     JSValue src1 = stackFrame.args[0].jsValue();
1761     JSValue src2 = stackFrame.args[1].jsValue();
1762     CallFrame* callFrame = stackFrame.callFrame;
1763
1764     bool result = jsLess<true>(callFrame, src1, src2);
1765     CHECK_FOR_EXCEPTION_AT_END();
1766     return result;
1767 }
1768
1769 DEFINE_STUB_FUNCTION(int, op_jlesseq)
1770 {
1771     STUB_INIT_STACK_FRAME(stackFrame);
1772
1773     JSValue src1 = stackFrame.args[0].jsValue();
1774     JSValue src2 = stackFrame.args[1].jsValue();
1775     CallFrame* callFrame = stackFrame.callFrame;
1776
1777     bool result = jsLessEq<true>(callFrame, src1, src2);
1778     CHECK_FOR_EXCEPTION_AT_END();
1779     return result;
1780 }
1781
1782 DEFINE_STUB_FUNCTION(int, op_jgreater)
1783 {
1784     STUB_INIT_STACK_FRAME(stackFrame);
1785
1786     JSValue src1 = stackFrame.args[0].jsValue();
1787     JSValue src2 = stackFrame.args[1].jsValue();
1788     CallFrame* callFrame = stackFrame.callFrame;
1789
1790     bool result = jsLess<false>(callFrame, src2, src1);
1791     CHECK_FOR_EXCEPTION_AT_END();
1792     return result;
1793 }
1794
1795 DEFINE_STUB_FUNCTION(int, op_jgreatereq)
1796 {
1797     STUB_INIT_STACK_FRAME(stackFrame);
1798
1799     JSValue src1 = stackFrame.args[0].jsValue();
1800     JSValue src2 = stackFrame.args[1].jsValue();
1801     CallFrame* callFrame = stackFrame.callFrame;
1802
1803     bool result = jsLessEq<false>(callFrame, src2, src1);
1804     CHECK_FOR_EXCEPTION_AT_END();
1805     return result;
1806 }
1807
1808 DEFINE_STUB_FUNCTION(int, op_jtrue)
1809 {
1810     STUB_INIT_STACK_FRAME(stackFrame);
1811
1812     JSValue src1 = stackFrame.args[0].jsValue();
1813
1814     bool result = src1.toBoolean(stackFrame.callFrame);
1815     CHECK_FOR_EXCEPTION_AT_END();
1816     return result;
1817 }
1818
1819 DEFINE_STUB_FUNCTION(int, op_eq)
1820 {
1821     STUB_INIT_STACK_FRAME(stackFrame);
1822
1823     JSValue src1 = stackFrame.args[0].jsValue();
1824     JSValue src2 = stackFrame.args[1].jsValue();
1825
1826 #if USE(JSVALUE32_64)
1827     start:
1828     if (src2.isUndefined()) {
1829         return src1.isNull() || 
1830                (src1.isCell() && src1.asCell()->structure()->masqueradesAsUndefined(stackFrame.callFrame->lexicalGlobalObject()))
1831                || src1.isUndefined();
1832     }
1833     
1834     if (src2.isNull()) {
1835         return src1.isUndefined() || 
1836                (src1.isCell() && src1.asCell()->structure()->masqueradesAsUndefined(stackFrame.callFrame->lexicalGlobalObject()))
1837                || src1.isNull();
1838     }
1839
1840     if (src1.isInt32()) {
1841         if (src2.isDouble())
1842             return src1.asInt32() == src2.asDouble();
1843         double d = src2.toNumber(stackFrame.callFrame);
1844         CHECK_FOR_EXCEPTION();
1845         return src1.asInt32() == d;
1846     }
1847
1848     if (src1.isDouble()) {
1849         if (src2.isInt32())
1850             return src1.asDouble() == src2.asInt32();
1851         double d = src2.toNumber(stackFrame.callFrame);
1852         CHECK_FOR_EXCEPTION();
1853         return src1.asDouble() == d;
1854     }
1855
1856     if (src1.isTrue()) {
1857         if (src2.isFalse())
1858             return false;
1859         double d = src2.toNumber(stackFrame.callFrame);
1860         CHECK_FOR_EXCEPTION();
1861         return d == 1.0;
1862     }
1863
1864     if (src1.isFalse()) {
1865         if (src2.isTrue())
1866             return false;
1867         double d = src2.toNumber(stackFrame.callFrame);
1868         CHECK_FOR_EXCEPTION();
1869         return d == 0.0;
1870     }
1871     
1872     if (src1.isUndefined())
1873         return src2.isCell() && src2.asCell()->structure()->masqueradesAsUndefined(stackFrame.callFrame->lexicalGlobalObject());
1874     
1875     if (src1.isNull())
1876         return src2.isCell() && src2.asCell()->structure()->masqueradesAsUndefined(stackFrame.callFrame->lexicalGlobalObject());
1877
1878     JSCell* cell1 = src1.asCell();
1879
1880     if (cell1->isString()) {
1881         if (src2.isInt32())
1882             return jsToNumber(jsCast<JSString*>(cell1)->value(stackFrame.callFrame)) == src2.asInt32();
1883             
1884         if (src2.isDouble())
1885             return jsToNumber(jsCast<JSString*>(cell1)->value(stackFrame.callFrame)) == src2.asDouble();
1886
1887         if (src2.isTrue())
1888             return jsToNumber(jsCast<JSString*>(cell1)->value(stackFrame.callFrame)) == 1.0;
1889
1890         if (src2.isFalse())
1891             return jsToNumber(jsCast<JSString*>(cell1)->value(stackFrame.callFrame)) == 0.0;
1892
1893         JSCell* cell2 = src2.asCell();
1894         if (cell2->isString())
1895             return jsCast<JSString*>(cell1)->value(stackFrame.callFrame) == jsCast<JSString*>(cell2)->value(stackFrame.callFrame);
1896
1897         src2 = asObject(cell2)->toPrimitive(stackFrame.callFrame);
1898         CHECK_FOR_EXCEPTION();
1899         goto start;
1900     }
1901
1902     if (src2.isObject())
1903         return asObject(cell1) == asObject(src2);
1904     src1 = asObject(cell1)->toPrimitive(stackFrame.callFrame);
1905     CHECK_FOR_EXCEPTION();
1906     goto start;
1907     
1908 #else // USE(JSVALUE32_64)
1909     CallFrame* callFrame = stackFrame.callFrame;
1910     
1911     bool result = JSValue::equalSlowCaseInline(callFrame, src1, src2);
1912     CHECK_FOR_EXCEPTION_AT_END();
1913     return result;
1914 #endif // USE(JSVALUE32_64)
1915 }
1916
1917 DEFINE_STUB_FUNCTION(int, op_eq_strings)
1918 {
1919 #if USE(JSVALUE32_64)
1920     STUB_INIT_STACK_FRAME(stackFrame);
1921
1922     JSString* string1 = stackFrame.args[0].jsString();
1923     JSString* string2 = stackFrame.args[1].jsString();
1924
1925     ASSERT(string1->isString());
1926     ASSERT(string2->isString());
1927     return string1->value(stackFrame.callFrame) == string2->value(stackFrame.callFrame);
1928 #else
1929     UNUSED_PARAM(args);
1930     RELEASE_ASSERT_NOT_REACHED();
1931     return 0;
1932 #endif
1933 }
1934
1935 DEFINE_STUB_FUNCTION(JSObject*, op_new_func_exp)
1936 {
1937     STUB_INIT_STACK_FRAME(stackFrame);
1938     CallFrame* callFrame = stackFrame.callFrame;
1939
1940     FunctionExecutable* function = stackFrame.args[0].function();
1941     JSFunction* func = JSFunction::create(callFrame, function, callFrame->scope());
1942     ASSERT(callFrame->codeBlock()->codeType() != FunctionCode || !callFrame->codeBlock()->needsFullScopeChain() || callFrame->uncheckedR(callFrame->codeBlock()->activationRegister()).jsValue());
1943
1944     return func;
1945 }
1946
1947 DEFINE_STUB_FUNCTION(JSObject*, op_new_regexp)
1948 {
1949     STUB_INIT_STACK_FRAME(stackFrame);
1950
1951     CallFrame* callFrame = stackFrame.callFrame;
1952
1953     RegExp* regExp = stackFrame.args[0].regExp();
1954     if (!regExp->isValid()) {
1955         stackFrame.vm->exception = createSyntaxError(callFrame, "Invalid flags supplied to RegExp constructor.");
1956         VM_THROW_EXCEPTION();
1957     }
1958
1959     return RegExpObject::create(*stackFrame.vm, stackFrame.callFrame->lexicalGlobalObject(), stackFrame.callFrame->lexicalGlobalObject()->regExpStructure(), regExp);
1960 }
1961
1962 DEFINE_STUB_FUNCTION(EncodedJSValue, op_call_eval)
1963 {
1964     STUB_INIT_STACK_FRAME(stackFrame);
1965
1966     CallFrame* callFrame = stackFrame.callFrame;
1967     CallFrame* callerFrame = callFrame->callerFrame();
1968     ASSERT(callFrame->callerFrame()->codeBlock()->codeType() != FunctionCode
1969         || !callFrame->callerFrame()->codeBlock()->needsFullScopeChain()
1970         || callFrame->callerFrame()->uncheckedR(callFrame->callerFrame()->codeBlock()->activationRegister()).jsValue());
1971
1972     callFrame->setScope(callerFrame->scope());
1973     callFrame->setReturnPC(static_cast<Instruction*>((STUB_RETURN_ADDRESS).value()));
1974     callFrame->setCodeBlock(0);
1975
1976     if (!isHostFunction(callFrame->calleeAsValue(), globalFuncEval))
1977         return JSValue::encode(JSValue());
1978
1979     JSValue result = eval(callFrame);
1980     if (stackFrame.vm->exception)
1981         return throwExceptionFromOpCall<EncodedJSValue>(stackFrame, callFrame, STUB_RETURN_ADDRESS);
1982
1983     return JSValue::encode(result);
1984 }
1985
1986 DEFINE_STUB_FUNCTION(void*, op_throw)
1987 {
1988     STUB_INIT_STACK_FRAME(stackFrame);
1989     ExceptionHandler handler = jitThrow(stackFrame.vm, stackFrame.callFrame, stackFrame.args[0].jsValue(), STUB_RETURN_ADDRESS);
1990     STUB_SET_RETURN_ADDRESS(handler.catchRoutine);
1991     return handler.callFrame;
1992 }
1993
1994 DEFINE_STUB_FUNCTION(JSPropertyNameIterator*, op_get_pnames)
1995 {
1996     STUB_INIT_STACK_FRAME(stackFrame);
1997
1998     CallFrame* callFrame = stackFrame.callFrame;
1999     JSObject* o = stackFrame.args[0].jsObject();
2000     Structure* structure = o->structure();
2001     JSPropertyNameIterator* jsPropertyNameIterator = structure->enumerationCache();
2002     if (!jsPropertyNameIterator || jsPropertyNameIterator->cachedPrototypeChain() != structure->prototypeChain(callFrame))
2003         jsPropertyNameIterator = JSPropertyNameIterator::create(callFrame, o);
2004     return jsPropertyNameIterator;
2005 }
2006
2007 DEFINE_STUB_FUNCTION(int, has_property)
2008 {
2009     STUB_INIT_STACK_FRAME(stackFrame);
2010
2011     JSObject* base = stackFrame.args[0].jsObject();
2012     JSString* property = stackFrame.args[1].jsString();
2013     int result = base->hasProperty(stackFrame.callFrame, Identifier(stackFrame.callFrame, property->value(stackFrame.callFrame)));
2014     CHECK_FOR_EXCEPTION_AT_END();
2015     return result;
2016 }
2017
2018 DEFINE_STUB_FUNCTION(void, op_push_with_scope)
2019 {
2020     STUB_INIT_STACK_FRAME(stackFrame);
2021
2022     JSObject* o = stackFrame.args[0].jsValue().toObject(stackFrame.callFrame);
2023     CHECK_FOR_EXCEPTION_VOID();
2024     stackFrame.callFrame->setScope(JSWithScope::create(stackFrame.callFrame, o));
2025 }
2026
2027 DEFINE_STUB_FUNCTION(void, op_pop_scope)
2028 {
2029     STUB_INIT_STACK_FRAME(stackFrame);
2030
2031     stackFrame.callFrame->setScope(stackFrame.callFrame->scope()->next());
2032 }
2033
2034 DEFINE_STUB_FUNCTION(void, op_push_name_scope)
2035 {
2036     STUB_INIT_STACK_FRAME(stackFrame);
2037
2038     JSNameScope* scope = JSNameScope::create(stackFrame.callFrame, stackFrame.args[0].identifier(), stackFrame.args[1].jsValue(), stackFrame.args[2].int32());
2039
2040     CallFrame* callFrame = stackFrame.callFrame;
2041     callFrame->setScope(scope);
2042 }
2043
2044 DEFINE_STUB_FUNCTION(void, op_put_by_index)
2045 {
2046     STUB_INIT_STACK_FRAME(stackFrame);
2047
2048     CallFrame* callFrame = stackFrame.callFrame;
2049     unsigned property = stackFrame.args[1].int32();
2050
2051     JSValue arrayValue = stackFrame.args[0].jsValue();
2052     ASSERT(isJSArray(arrayValue));
2053     asArray(arrayValue)->putDirectIndex(callFrame, property, stackFrame.args[2].jsValue());
2054 }
2055
2056 DEFINE_STUB_FUNCTION(void*, op_switch_imm)
2057 {
2058     STUB_INIT_STACK_FRAME(stackFrame);
2059
2060     JSValue scrutinee = stackFrame.args[0].jsValue();
2061     unsigned tableIndex = stackFrame.args[1].int32();
2062     CallFrame* callFrame = stackFrame.callFrame;
2063     CodeBlock* codeBlock = callFrame->codeBlock();
2064
2065     if (scrutinee.isInt32())
2066         return codeBlock->switchJumpTable(tableIndex).ctiForValue(scrutinee.asInt32()).executableAddress();
2067     if (scrutinee.isDouble() && scrutinee.asDouble() == static_cast<int32_t>(scrutinee.asDouble()))
2068         return codeBlock->switchJumpTable(tableIndex).ctiForValue(static_cast<int32_t>(scrutinee.asDouble())).executableAddress();
2069     return codeBlock->switchJumpTable(tableIndex).ctiDefault.executableAddress();
2070 }
2071
2072 DEFINE_STUB_FUNCTION(void*, op_switch_char)
2073 {
2074     STUB_INIT_STACK_FRAME(stackFrame);
2075
2076     JSValue scrutinee = stackFrame.args[0].jsValue();
2077     unsigned tableIndex = stackFrame.args[1].int32();
2078     CallFrame* callFrame = stackFrame.callFrame;
2079     CodeBlock* codeBlock = callFrame->codeBlock();
2080
2081     void* result = codeBlock->switchJumpTable(tableIndex).ctiDefault.executableAddress();
2082
2083     if (scrutinee.isString()) {
2084         StringImpl* value = asString(scrutinee)->value(callFrame).impl();
2085         if (value->length() == 1)
2086             result = codeBlock->switchJumpTable(tableIndex).ctiForValue((*value)[0]).executableAddress();
2087     }
2088
2089     CHECK_FOR_EXCEPTION_AT_END();
2090     return result;
2091 }
2092
2093 DEFINE_STUB_FUNCTION(void*, op_switch_string)
2094 {
2095     STUB_INIT_STACK_FRAME(stackFrame);
2096
2097     JSValue scrutinee = stackFrame.args[0].jsValue();
2098     unsigned tableIndex = stackFrame.args[1].int32();
2099     CallFrame* callFrame = stackFrame.callFrame;
2100     CodeBlock* codeBlock = callFrame->codeBlock();
2101
2102     void* result = codeBlock->stringSwitchJumpTable(tableIndex).ctiDefault.executableAddress();
2103
2104     if (scrutinee.isString()) {
2105         StringImpl* value = asString(scrutinee)->value(callFrame).impl();
2106         result = codeBlock->stringSwitchJumpTable(tableIndex).ctiForValue(value).executableAddress();
2107     }
2108
2109     CHECK_FOR_EXCEPTION_AT_END();
2110     return result;
2111 }
2112
2113 DEFINE_STUB_FUNCTION(void, op_put_getter_setter)
2114 {
2115     STUB_INIT_STACK_FRAME(stackFrame);
2116
2117     CallFrame* callFrame = stackFrame.callFrame;
2118
2119     ASSERT(stackFrame.args[0].jsValue().isObject());
2120     JSObject* baseObj = asObject(stackFrame.args[0].jsValue());
2121
2122     GetterSetter* accessor = GetterSetter::create(callFrame);
2123
2124     JSValue getter = stackFrame.args[2].jsValue();
2125     JSValue setter = stackFrame.args[3].jsValue();
2126     ASSERT(getter.isObject() || getter.isUndefined());
2127     ASSERT(setter.isObject() || setter.isUndefined());
2128     ASSERT(getter.isObject() || setter.isObject());
2129
2130     if (!getter.isUndefined())
2131         accessor->setGetter(callFrame->vm(), asObject(getter));
2132     if (!setter.isUndefined())
2133         accessor->setSetter(callFrame->vm(), asObject(setter));
2134     baseObj->putDirectAccessor(callFrame, stackFrame.args[1].identifier(), accessor, Accessor);
2135 }
2136
2137 DEFINE_STUB_FUNCTION(void, op_throw_static_error)
2138 {
2139     STUB_INIT_STACK_FRAME(stackFrame);
2140
2141     CallFrame* callFrame = stackFrame.callFrame;
2142     String message = errorDescriptionForValue(callFrame, stackFrame.args[0].jsValue())->value(callFrame);
2143     if (stackFrame.args[1].asInt32)
2144         stackFrame.vm->exception = createReferenceError(callFrame, message);
2145     else
2146         stackFrame.vm->exception = createTypeError(callFrame, message);
2147     VM_THROW_EXCEPTION_AT_END();
2148 }
2149
2150 DEFINE_STUB_FUNCTION(void, op_debug)
2151 {
2152     STUB_INIT_STACK_FRAME(stackFrame);
2153
2154     CallFrame* callFrame = stackFrame.callFrame;
2155
2156     int debugHookID = stackFrame.args[0].int32();
2157     int firstLine = stackFrame.args[1].int32();
2158     int lastLine = stackFrame.args[2].int32();
2159     int column = stackFrame.args[3].int32();
2160
2161     stackFrame.vm->interpreter->debug(callFrame, static_cast<DebugHookID>(debugHookID), firstLine, lastLine, column);
2162 }
2163
2164 DEFINE_STUB_FUNCTION(void*, vm_throw)
2165 {
2166     STUB_INIT_STACK_FRAME(stackFrame);
2167     VM* vm = stackFrame.vm;
2168     ExceptionHandler handler = jitThrow(vm, stackFrame.callFrame, vm->exception, vm->exceptionLocation);
2169     STUB_SET_RETURN_ADDRESS(handler.catchRoutine);
2170     return handler.callFrame;
2171 }
2172
2173 #if USE(JSVALUE32_64)
2174 EncodedExceptionHandler JIT_STUB cti_vm_handle_exception(CallFrame* callFrame)
2175 {
2176     ASSERT(!callFrame->hasHostCallFrameFlag());
2177     if (!callFrame) {
2178         // The entire stack has already been unwound. Nothing more to handle.
2179         return encode(uncaughtExceptionHandler());
2180     }
2181
2182     VM* vm = callFrame->codeBlock()->vm();
2183     vm->topCallFrame = callFrame;
2184     return encode(jitThrowNew(vm, callFrame, vm->exception));
2185 }
2186 #else
2187 ExceptionHandler JIT_STUB cti_vm_handle_exception(CallFrame* callFrame)
2188 {
2189     ASSERT(!callFrame->hasHostCallFrameFlag());
2190     if (!callFrame) {
2191         // The entire stack has already been unwound. Nothing more to handle.
2192         return uncaughtExceptionHandler();
2193     }
2194
2195     VM* vm = callFrame->codeBlock()->vm();
2196     vm->topCallFrame = callFrame;
2197     return jitThrowNew(vm, callFrame, vm->exception);
2198 }
2199 #endif
2200
2201 DEFINE_STUB_FUNCTION(EncodedJSValue, to_object)
2202 {
2203     STUB_INIT_STACK_FRAME(stackFrame);
2204
2205     CallFrame* callFrame = stackFrame.callFrame;
2206     return JSValue::encode(stackFrame.args[0].jsValue().toObject(callFrame));
2207 }
2208
2209 DEFINE_STUB_FUNCTION(EncodedJSValue, op_resolve_scope)
2210 {
2211     STUB_INIT_STACK_FRAME(stackFrame);
2212     ExecState* exec = stackFrame.callFrame;
2213     Instruction* pc = stackFrame.args[0].pc();
2214
2215     const Identifier& ident = exec->codeBlock()->identifier(pc[2].u.operand);
2216     return JSValue::encode(JSScope::resolve(exec, exec->scope(), ident));
2217 }
2218
2219 DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_from_scope)
2220 {
2221     STUB_INIT_STACK_FRAME(stackFrame);
2222     ExecState* exec = stackFrame.callFrame;
2223     Instruction* pc = stackFrame.args[0].pc();
2224
2225     const Identifier& ident = exec->codeBlock()->identifier(pc[3].u.operand);
2226     JSObject* scope = jsCast<JSObject*>(exec->uncheckedR(pc[2].u.operand).jsValue());
2227     ResolveModeAndType modeAndType(pc[4].u.operand);
2228
2229     PropertySlot slot(scope);
2230     if (!scope->getPropertySlot(exec, ident, slot)) {
2231         if (modeAndType.mode() == ThrowIfNotFound) {
2232             throwError(exec, createUndefinedVariableError(exec, ident));
2233             VM_THROW_EXCEPTION();
2234         }
2235         return JSValue::encode(jsUndefined());
2236     }
2237
2238     // Covers implicit globals. Since they don't exist until they first execute, we didn't know how to cache them at compile time.
2239     if (slot.isCacheableValue() && slot.slotBase() == scope && scope->structure()->propertyAccessesAreCacheable()) {
2240         if (modeAndType.type() == GlobalProperty || modeAndType.type() == GlobalPropertyWithVarInjectionChecks) {
2241             CodeBlock* codeBlock = exec->codeBlock();
2242             ConcurrentJITLocker locker(codeBlock->m_lock);
2243             pc[5].u.structure.set(exec->vm(), codeBlock->ownerExecutable(), scope->structure());
2244             pc[6].u.operand = slot.cachedOffset();
2245         }
2246     }
2247
2248     return JSValue::encode(slot.getValue(exec, ident));
2249 }
2250
2251 DEFINE_STUB_FUNCTION(void, op_put_to_scope)
2252 {
2253     STUB_INIT_STACK_FRAME(stackFrame);
2254     ExecState* exec = stackFrame.callFrame;
2255     Instruction* pc = stackFrame.args[0].pc();
2256
2257     CodeBlock* codeBlock = exec->codeBlock();
2258     const Identifier& ident = codeBlock->identifier(pc[2].u.operand);
2259     JSObject* scope = jsCast<JSObject*>(exec->uncheckedR(pc[1].u.operand).jsValue());
2260     JSValue value = exec->r(pc[3].u.operand).jsValue();
2261     ResolveModeAndType modeAndType = ResolveModeAndType(pc[4].u.operand);
2262
2263     if (modeAndType.mode() == ThrowIfNotFound && !scope->hasProperty(exec, ident)) {
2264         throwError(exec, createUndefinedVariableError(exec, ident));
2265         VM_THROW_EXCEPTION_AT_END();
2266         return;
2267     }
2268
2269     PutPropertySlot slot(codeBlock->isStrictMode());
2270     scope->methodTable()->put(scope, exec, ident, value, slot);
2271     
2272     if (exec->vm().exception) {
2273         VM_THROW_EXCEPTION_AT_END();
2274         return;
2275     }
2276
2277     // Covers implicit globals. Since they don't exist until they first execute, we didn't know how to cache them at compile time.
2278     if (modeAndType.type() == GlobalProperty || modeAndType.type() == GlobalPropertyWithVarInjectionChecks) {
2279         if (slot.isCacheable() && slot.base() == scope && scope->structure()->propertyAccessesAreCacheable()) {
2280             ConcurrentJITLocker locker(codeBlock->m_lock);
2281             pc[5].u.structure.set(exec->vm(), codeBlock->ownerExecutable(), scope->structure());
2282             pc[6].u.operand = slot.cachedOffset();
2283         }
2284     }
2285 }
2286
2287 } // namespace JSC
2288
2289 #endif // ENABLE(JIT)