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