OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 2008, 2009 Apple Inc. All rights reserved. | 2 * Copyright (C) 2008, 2009 Apple Inc. All rights reserved. |
3 * Copyright (C) 2008 Cameron Zwarich <cwzwarich@uwaterloo.ca> | 3 * Copyright (C) 2008 Cameron Zwarich <cwzwarich@uwaterloo.ca> |
4 * | 4 * |
5 * Redistribution and use in source and binary forms, with or without | 5 * Redistribution and use in source and binary forms, with or without |
6 * modification, are permitted provided that the following conditions | 6 * modification, are permitted provided that the following conditions |
7 * are met: | 7 * are met: |
8 * | 8 * |
9 * 1. Redistributions of source code must retain the above copyright | 9 * 1. Redistributions of source code must retain the above copyright |
10 * notice, this list of conditions and the following disclaimer. | 10 * notice, this list of conditions and the following disclaimer. |
(...skipping 329 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
340 | 340 |
341 JSValuePtr result = jsUndefined(); | 341 JSValuePtr result = jsUndefined(); |
342 if (evalNode) | 342 if (evalNode) |
343 result = callFrame->globalData().interpreter->execute(evalNode.get(), ca
llFrame, callFrame->thisValue().toThisObject(callFrame), callFrame->registers()
- registerFile->start() + registerOffset, scopeChain, &exceptionValue); | 343 result = callFrame->globalData().interpreter->execute(evalNode.get(), ca
llFrame, callFrame->thisValue().toThisObject(callFrame), callFrame->registers()
- registerFile->start() + registerOffset, scopeChain, &exceptionValue); |
344 | 344 |
345 return result; | 345 return result; |
346 } | 346 } |
347 | 347 |
348 Interpreter::Interpreter() | 348 Interpreter::Interpreter() |
349 : m_sampler(0) | 349 : m_sampler(0) |
350 #if ENABLE(JIT) | |
351 , m_ctiArrayLengthTrampoline(0) | |
352 , m_ctiStringLengthTrampoline(0) | |
353 , m_ctiVirtualCallPreLink(0) | |
354 , m_ctiVirtualCallLink(0) | |
355 , m_ctiVirtualCall(0) | |
356 #endif | |
357 , m_reentryDepth(0) | 350 , m_reentryDepth(0) |
358 { | 351 { |
359 privateExecute(InitializeAndReturn, 0, 0, 0); | 352 privateExecute(InitializeAndReturn, 0, 0, 0); |
360 | |
361 // Bizarrely, calling fastMalloc here is faster than allocating space on the
stack. | |
362 void* storage = fastMalloc(sizeof(CollectorBlock)); | |
363 | |
364 JSCell* jsArray = new (storage) JSArray(JSArray::createStructure(jsNull())); | |
365 m_jsArrayVptr = jsArray->vptr(); | |
366 jsArray->~JSCell(); | |
367 | |
368 JSCell* jsByteArray = new (storage) JSByteArray(JSByteArray::VPtrStealingHac
k); | |
369 m_jsByteArrayVptr = jsByteArray->vptr(); | |
370 jsByteArray->~JSCell(); | |
371 | |
372 JSCell* jsString = new (storage) JSString(JSString::VPtrStealingHack); | |
373 m_jsStringVptr = jsString->vptr(); | |
374 jsString->~JSCell(); | |
375 | |
376 JSCell* jsFunction = new (storage) JSFunction(JSFunction::createStructure(js
Null())); | |
377 m_jsFunctionVptr = jsFunction->vptr(); | |
378 jsFunction->~JSCell(); | |
379 | |
380 fastFree(storage); | |
381 } | |
382 | |
383 void Interpreter::initialize(JSGlobalData* globalData) | |
384 { | |
385 #if ENABLE(JIT) | |
386 JIT::compileCTIMachineTrampolines(globalData); | |
387 #else | |
388 UNUSED_PARAM(globalData); | |
389 #endif | |
390 } | |
391 | |
392 Interpreter::~Interpreter() | |
393 { | |
394 } | 353 } |
395 | 354 |
396 #ifndef NDEBUG | 355 #ifndef NDEBUG |
397 | 356 |
398 void Interpreter::dumpCallFrame(CallFrame* callFrame) | 357 void Interpreter::dumpCallFrame(CallFrame* callFrame) |
399 { | 358 { |
400 callFrame->codeBlock()->dump(callFrame); | 359 callFrame->codeBlock()->dump(callFrame); |
401 dumpRegisters(callFrame); | 360 dumpRegisters(callFrame); |
402 } | 361 } |
403 | 362 |
(...skipping 551 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
955 // Recursive invocation may already have specialized this instruction. | 914 // Recursive invocation may already have specialized this instruction. |
956 if (vPC[0].u.opcode != getOpcode(op_get_by_id)) | 915 if (vPC[0].u.opcode != getOpcode(op_get_by_id)) |
957 return; | 916 return; |
958 | 917 |
959 // FIXME: Cache property access for immediates. | 918 // FIXME: Cache property access for immediates. |
960 if (!baseValue.isCell()) { | 919 if (!baseValue.isCell()) { |
961 vPC[0] = getOpcode(op_get_by_id_generic); | 920 vPC[0] = getOpcode(op_get_by_id_generic); |
962 return; | 921 return; |
963 } | 922 } |
964 | 923 |
965 if (isJSArray(baseValue) && propertyName == callFrame->propertyNames().lengt
h) { | 924 JSGlobalData* globalData = &callFrame->globalData(); |
| 925 if (isJSArray(globalData, baseValue) && propertyName == callFrame->propertyN
ames().length) { |
966 vPC[0] = getOpcode(op_get_array_length); | 926 vPC[0] = getOpcode(op_get_array_length); |
967 return; | 927 return; |
968 } | 928 } |
969 | 929 |
970 if (isJSString(baseValue) && propertyName == callFrame->propertyNames().leng
th) { | 930 if (isJSString(globalData, baseValue) && propertyName == callFrame->property
Names().length) { |
971 vPC[0] = getOpcode(op_get_string_length); | 931 vPC[0] = getOpcode(op_get_string_length); |
972 return; | 932 return; |
973 } | 933 } |
974 | 934 |
975 // Uncacheable: give up. | 935 // Uncacheable: give up. |
976 if (!slot.isCacheable()) { | 936 if (!slot.isCacheable()) { |
977 vPC[0] = getOpcode(op_get_by_id_generic); | 937 vPC[0] = getOpcode(op_get_by_id_generic); |
978 return; | 938 return; |
979 } | 939 } |
980 | 940 |
(...skipping 1285 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2266 DEFINE_OPCODE(op_get_array_length) { | 2226 DEFINE_OPCODE(op_get_array_length) { |
2267 /* op_get_array_length dst(r) base(r) property(id) nop(sID) nop(n) nop(n
) nop(n) | 2227 /* op_get_array_length dst(r) base(r) property(id) nop(sID) nop(n) nop(n
) nop(n) |
2268 | 2228 |
2269 Cached property access: Gets the length of the array in register base
, | 2229 Cached property access: Gets the length of the array in register base
, |
2270 and puts the result in register dst. If register base does not hold | 2230 and puts the result in register dst. If register base does not hold |
2271 an array, op_get_array_length reverts to op_get_by_id. | 2231 an array, op_get_array_length reverts to op_get_by_id. |
2272 */ | 2232 */ |
2273 | 2233 |
2274 int base = vPC[2].u.operand; | 2234 int base = vPC[2].u.operand; |
2275 JSValuePtr baseValue = callFrame[base].jsValue(callFrame); | 2235 JSValuePtr baseValue = callFrame[base].jsValue(callFrame); |
2276 if (LIKELY(isJSArray(baseValue))) { | 2236 if (LIKELY(isJSArray(globalData, baseValue))) { |
2277 int dst = vPC[1].u.operand; | 2237 int dst = vPC[1].u.operand; |
2278 callFrame[dst] = JSValuePtr(jsNumber(callFrame, asArray(baseValue)->
length())); | 2238 callFrame[dst] = JSValuePtr(jsNumber(callFrame, asArray(baseValue)->
length())); |
2279 vPC += 8; | 2239 vPC += 8; |
2280 NEXT_INSTRUCTION(); | 2240 NEXT_INSTRUCTION(); |
2281 } | 2241 } |
2282 | 2242 |
2283 uncacheGetByID(callFrame->codeBlock(), vPC); | 2243 uncacheGetByID(callFrame->codeBlock(), vPC); |
2284 NEXT_INSTRUCTION(); | 2244 NEXT_INSTRUCTION(); |
2285 } | 2245 } |
2286 DEFINE_OPCODE(op_get_string_length) { | 2246 DEFINE_OPCODE(op_get_string_length) { |
2287 /* op_get_string_length dst(r) base(r) property(id) nop(sID) nop(n) nop(
n) nop(n) | 2247 /* op_get_string_length dst(r) base(r) property(id) nop(sID) nop(n) nop(
n) nop(n) |
2288 | 2248 |
2289 Cached property access: Gets the length of the string in register bas
e, | 2249 Cached property access: Gets the length of the string in register bas
e, |
2290 and puts the result in register dst. If register base does not hold | 2250 and puts the result in register dst. If register base does not hold |
2291 a string, op_get_string_length reverts to op_get_by_id. | 2251 a string, op_get_string_length reverts to op_get_by_id. |
2292 */ | 2252 */ |
2293 | 2253 |
2294 int base = vPC[2].u.operand; | 2254 int base = vPC[2].u.operand; |
2295 JSValuePtr baseValue = callFrame[base].jsValue(callFrame); | 2255 JSValuePtr baseValue = callFrame[base].jsValue(callFrame); |
2296 if (LIKELY(isJSString(baseValue))) { | 2256 if (LIKELY(isJSString(globalData, baseValue))) { |
2297 int dst = vPC[1].u.operand; | 2257 int dst = vPC[1].u.operand; |
2298 callFrame[dst] = JSValuePtr(jsNumber(callFrame, asString(baseValue)-
>value().size())); | 2258 callFrame[dst] = JSValuePtr(jsNumber(callFrame, asString(baseValue)-
>value().size())); |
2299 vPC += 8; | 2259 vPC += 8; |
2300 NEXT_INSTRUCTION(); | 2260 NEXT_INSTRUCTION(); |
2301 } | 2261 } |
2302 | 2262 |
2303 uncacheGetByID(callFrame->codeBlock(), vPC); | 2263 uncacheGetByID(callFrame->codeBlock(), vPC); |
2304 NEXT_INSTRUCTION(); | 2264 NEXT_INSTRUCTION(); |
2305 } | 2265 } |
2306 DEFINE_OPCODE(op_put_by_id) { | 2266 DEFINE_OPCODE(op_put_by_id) { |
(...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2468 int base = (++vPC)->u.operand; | 2428 int base = (++vPC)->u.operand; |
2469 int property = (++vPC)->u.operand; | 2429 int property = (++vPC)->u.operand; |
2470 | 2430 |
2471 JSValuePtr baseValue = callFrame[base].jsValue(callFrame); | 2431 JSValuePtr baseValue = callFrame[base].jsValue(callFrame); |
2472 JSValuePtr subscript = callFrame[property].jsValue(callFrame); | 2432 JSValuePtr subscript = callFrame[property].jsValue(callFrame); |
2473 | 2433 |
2474 JSValuePtr result; | 2434 JSValuePtr result; |
2475 | 2435 |
2476 if (LIKELY(subscript.isUInt32Fast())) { | 2436 if (LIKELY(subscript.isUInt32Fast())) { |
2477 uint32_t i = subscript.getUInt32Fast(); | 2437 uint32_t i = subscript.getUInt32Fast(); |
2478 if (isJSArray(baseValue)) { | 2438 if (isJSArray(globalData, baseValue)) { |
2479 JSArray* jsArray = asArray(baseValue); | 2439 JSArray* jsArray = asArray(baseValue); |
2480 if (jsArray->canGetIndex(i)) | 2440 if (jsArray->canGetIndex(i)) |
2481 result = jsArray->getIndex(i); | 2441 result = jsArray->getIndex(i); |
2482 else | 2442 else |
2483 result = jsArray->JSArray::get(callFrame, i); | 2443 result = jsArray->JSArray::get(callFrame, i); |
2484 } else if (isJSString(baseValue) && asString(baseValue)->canGetIndex
(i)) | 2444 } else if (isJSString(globalData, baseValue) && asString(baseValue)-
>canGetIndex(i)) |
2485 result = asString(baseValue)->getIndex(&callFrame->globalData(),
i); | 2445 result = asString(baseValue)->getIndex(&callFrame->globalData(),
i); |
2486 else if (isJSByteArray(baseValue) && asByteArray(baseValue)->canAcce
ssIndex(i)) | 2446 else if (isJSByteArray(globalData, baseValue) && asByteArray(baseVal
ue)->canAccessIndex(i)) |
2487 result = asByteArray(baseValue)->getIndex(callFrame, i); | 2447 result = asByteArray(baseValue)->getIndex(callFrame, i); |
2488 else | 2448 else |
2489 result = baseValue.get(callFrame, i); | 2449 result = baseValue.get(callFrame, i); |
2490 } else { | 2450 } else { |
2491 Identifier property(callFrame, subscript.toString(callFrame)); | 2451 Identifier property(callFrame, subscript.toString(callFrame)); |
2492 result = baseValue.get(callFrame, property); | 2452 result = baseValue.get(callFrame, property); |
2493 } | 2453 } |
2494 | 2454 |
2495 CHECK_FOR_EXCEPTION(); | 2455 CHECK_FOR_EXCEPTION(); |
2496 callFrame[dst] = result; | 2456 callFrame[dst] = result; |
(...skipping 13 matching lines...) Expand all Loading... |
2510 */ | 2470 */ |
2511 int base = (++vPC)->u.operand; | 2471 int base = (++vPC)->u.operand; |
2512 int property = (++vPC)->u.operand; | 2472 int property = (++vPC)->u.operand; |
2513 int value = (++vPC)->u.operand; | 2473 int value = (++vPC)->u.operand; |
2514 | 2474 |
2515 JSValuePtr baseValue = callFrame[base].jsValue(callFrame); | 2475 JSValuePtr baseValue = callFrame[base].jsValue(callFrame); |
2516 JSValuePtr subscript = callFrame[property].jsValue(callFrame); | 2476 JSValuePtr subscript = callFrame[property].jsValue(callFrame); |
2517 | 2477 |
2518 if (LIKELY(subscript.isUInt32Fast())) { | 2478 if (LIKELY(subscript.isUInt32Fast())) { |
2519 uint32_t i = subscript.getUInt32Fast(); | 2479 uint32_t i = subscript.getUInt32Fast(); |
2520 if (isJSArray(baseValue)) { | 2480 if (isJSArray(globalData, baseValue)) { |
2521 JSArray* jsArray = asArray(baseValue); | 2481 JSArray* jsArray = asArray(baseValue); |
2522 if (jsArray->canSetIndex(i)) | 2482 if (jsArray->canSetIndex(i)) |
2523 jsArray->setIndex(i, callFrame[value].jsValue(callFrame)); | 2483 jsArray->setIndex(i, callFrame[value].jsValue(callFrame)); |
2524 else | 2484 else |
2525 jsArray->JSArray::put(callFrame, i, callFrame[value].jsValue
(callFrame)); | 2485 jsArray->JSArray::put(callFrame, i, callFrame[value].jsValue
(callFrame)); |
2526 } else if (isJSByteArray(baseValue) && asByteArray(baseValue)->canAc
cessIndex(i)) { | 2486 } else if (isJSByteArray(globalData, baseValue) && asByteArray(baseV
alue)->canAccessIndex(i)) { |
2527 JSByteArray* jsByteArray = asByteArray(baseValue); | 2487 JSByteArray* jsByteArray = asByteArray(baseValue); |
2528 double dValue = 0; | 2488 double dValue = 0; |
2529 JSValuePtr jsValue = callFrame[value].jsValue(callFrame); | 2489 JSValuePtr jsValue = callFrame[value].jsValue(callFrame); |
2530 if (jsValue.isInt32Fast()) | 2490 if (jsValue.isInt32Fast()) |
2531 jsByteArray->setIndex(i, jsValue.getInt32Fast()); | 2491 jsByteArray->setIndex(i, jsValue.getInt32Fast()); |
2532 else if (jsValue.getNumber(dValue)) | 2492 else if (jsValue.getNumber(dValue)) |
2533 jsByteArray->setIndex(i, dValue); | 2493 jsByteArray->setIndex(i, dValue); |
2534 else | 2494 else |
2535 baseValue.put(callFrame, i, jsValue); | 2495 baseValue.put(callFrame, i, jsValue); |
2536 } else | 2496 } else |
(...skipping 1130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3667 if (candidate->callee() == function) | 3627 if (candidate->callee() == function) |
3668 return candidate; | 3628 return candidate; |
3669 } | 3629 } |
3670 return 0; | 3630 return 0; |
3671 } | 3631 } |
3672 | 3632 |
3673 } // namespace JSC | 3633 } // namespace JSC |
3674 | 3634 |
3675 | 3635 |
3676 | 3636 |
OLD | NEW |