| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (C) 2008 Apple Inc. All rights reserved. | 2 * Copyright (C) 2008 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 1201 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1212 | 1212 |
| 1213 | 1213 |
| 1214 RegisterID* CodeGenerator::emitNewFunctionExpression(RegisterID* r0, FuncExprNod
e* n) | 1214 RegisterID* CodeGenerator::emitNewFunctionExpression(RegisterID* r0, FuncExprNod
e* n) |
| 1215 { | 1215 { |
| 1216 emitOpcode(op_new_func_exp); | 1216 emitOpcode(op_new_func_exp); |
| 1217 instructions().append(r0->index()); | 1217 instructions().append(r0->index()); |
| 1218 instructions().append(addConstant(n)); | 1218 instructions().append(addConstant(n)); |
| 1219 return r0; | 1219 return r0; |
| 1220 } | 1220 } |
| 1221 | 1221 |
| 1222 RegisterID* CodeGenerator::emitCall(RegisterID* dst, RegisterID* func, RegisterI
D* base, ArgumentsNode* argumentsNode, unsigned divot, unsigned startOffset, uns
igned endOffset) | 1222 RegisterID* CodeGenerator::emitCall(RegisterID* dst, RegisterID* func, RegisterI
D* thisRegister, ArgumentsNode* argumentsNode, unsigned divot, unsigned startOff
set, unsigned endOffset) |
| 1223 { | 1223 { |
| 1224 return emitCall(op_call, dst, func, base, argumentsNode, divot, startOffset,
endOffset); | 1224 return emitCall(op_call, dst, func, thisRegister, argumentsNode, divot, star
tOffset, endOffset); |
| 1225 } | 1225 } |
| 1226 | 1226 |
| 1227 RegisterID* CodeGenerator::emitCallEval(RegisterID* dst, RegisterID* func, Regis
terID* base, ArgumentsNode* argumentsNode, unsigned divot, unsigned startOffset,
unsigned endOffset) | 1227 RegisterID* CodeGenerator::emitCallEval(RegisterID* dst, RegisterID* func, Regis
terID* thisRegister, ArgumentsNode* argumentsNode, unsigned divot, unsigned star
tOffset, unsigned endOffset) |
| 1228 { | 1228 { |
| 1229 return emitCall(op_call_eval, dst, func, base, argumentsNode, divot, startOf
fset, endOffset); | 1229 return emitCall(op_call_eval, dst, func, thisRegister, argumentsNode, divot,
startOffset, endOffset); |
| 1230 } | 1230 } |
| 1231 | 1231 |
| 1232 RegisterID* CodeGenerator::emitCall(OpcodeID opcodeID, RegisterID* dst, Register
ID* func, RegisterID* base, ArgumentsNode* argumentsNode, unsigned divot, unsign
ed startOffset, unsigned endOffset) | 1232 RegisterID* CodeGenerator::emitCall(OpcodeID opcodeID, RegisterID* dst, Register
ID* func, RegisterID* thisRegister, ArgumentsNode* argumentsNode, unsigned divot
, unsigned startOffset, unsigned endOffset) |
| 1233 { | 1233 { |
| 1234 ASSERT(opcodeID == op_call || opcodeID == op_call_eval); | 1234 ASSERT(opcodeID == op_call || opcodeID == op_call_eval); |
| 1235 ASSERT(func->refCount()); | 1235 ASSERT(func->refCount()); |
| 1236 ASSERT(!base || base->refCount()); | 1236 |
| 1237 | 1237 if (m_shouldEmitProfileHooks) { |
| 1238 // If codegen decided to recycle func as this call's destination registe
r, |
| 1239 // we need to undo that optimization here so that func will still be aro
und |
| 1240 // for the sake of op_profile_did_call. |
| 1241 if (dst == func) { |
| 1242 RefPtr<RegisterID> protect = thisRegister; |
| 1243 RefPtr<RegisterID> movedThisRegister = emitMove(newTemporary(), this
Register); |
| 1244 RefPtr<RegisterID> movedFunc = emitMove(thisRegister, func); |
| 1245 |
| 1246 thisRegister = movedThisRegister.release().releaseRef(); |
| 1247 func = movedFunc.release().releaseRef(); |
| 1248 } |
| 1249 } |
| 1250 |
| 1238 // Generate code for arguments. | 1251 // Generate code for arguments. |
| 1239 Vector<RefPtr<RegisterID>, 16> argv; | 1252 Vector<RefPtr<RegisterID>, 16> argv; |
| 1240 argv.append(newTemporary()); // reserve space for "this" | 1253 argv.append(thisRegister); |
| 1241 for (ArgumentListNode* n = argumentsNode->m_listNode.get(); n; n = n->m_next
.get()) { | 1254 for (ArgumentListNode* n = argumentsNode->m_listNode.get(); n; n = n->m_next
.get()) { |
| 1242 argv.append(newTemporary()); | 1255 argv.append(newTemporary()); |
| 1243 emitNode(argv.last().get(), n); | 1256 emitNode(argv.last().get(), n); |
| 1244 } | 1257 } |
| 1245 | 1258 |
| 1246 // Reserve space for call frame. | 1259 // Reserve space for call frame. |
| 1247 Vector<RefPtr<RegisterID>, RegisterFile::CallFrameHeaderSize> callFrame; | 1260 Vector<RefPtr<RegisterID>, RegisterFile::CallFrameHeaderSize> callFrame; |
| 1248 for (int i = 0; i < RegisterFile::CallFrameHeaderSize; ++i) | 1261 for (int i = 0; i < RegisterFile::CallFrameHeaderSize; ++i) |
| 1249 callFrame.append(newTemporary()); | 1262 callFrame.append(newTemporary()); |
| 1250 | 1263 |
| 1251 if (m_shouldEmitProfileHooks) { | 1264 if (m_shouldEmitProfileHooks) { |
| 1252 emitOpcode(op_profile_will_call); | 1265 emitOpcode(op_profile_will_call); |
| 1253 instructions().append(func->index()); | 1266 instructions().append(func->index()); |
| 1254 } | 1267 } |
| 1255 | 1268 |
| 1256 emitExpressionInfo(divot, startOffset, endOffset); | 1269 emitExpressionInfo(divot, startOffset, endOffset); |
| 1257 m_codeBlock->callLinkInfos.append(CallLinkInfo()); | 1270 m_codeBlock->callLinkInfos.append(CallLinkInfo()); |
| 1271 |
| 1272 // Emit call. |
| 1258 emitOpcode(opcodeID); | 1273 emitOpcode(opcodeID); |
| 1259 instructions().append(dst->index()); | 1274 instructions().append(dst->index()); // dst |
| 1260 instructions().append(func->index()); | 1275 instructions().append(func->index()); // func |
| 1261 instructions().append(base ? base->index() : missingThisObjectMarker()); //
We encode the "this" value in the instruction stream, to avoid an explicit instr
uction for copying or loading it. | 1276 instructions().append(argv.size()); // argCount |
| 1262 instructions().append(argv[0]->index()); // argv | |
| 1263 instructions().append(argv.size()); // argc | |
| 1264 instructions().append(argv[0]->index() + argv.size() + RegisterFile::CallFra
meHeaderSize); // registerOffset | 1277 instructions().append(argv[0]->index() + argv.size() + RegisterFile::CallFra
meHeaderSize); // registerOffset |
| 1265 | 1278 |
| 1266 if (m_shouldEmitProfileHooks) { | 1279 if (m_shouldEmitProfileHooks) { |
| 1267 emitOpcode(op_profile_did_call); | 1280 emitOpcode(op_profile_did_call); |
| 1268 instructions().append(func->index()); | 1281 instructions().append(func->index()); |
| 1282 |
| 1283 if (dst == func) { |
| 1284 thisRegister->deref(); |
| 1285 func->deref(); |
| 1286 } |
| 1269 } | 1287 } |
| 1270 | 1288 |
| 1271 return dst; | 1289 return dst; |
| 1272 } | 1290 } |
| 1273 | 1291 |
| 1274 RegisterID* CodeGenerator::emitReturn(RegisterID* src) | 1292 RegisterID* CodeGenerator::emitReturn(RegisterID* src) |
| 1275 { | 1293 { |
| 1276 if (m_codeBlock->needsFullScopeChain) { | 1294 if (m_codeBlock->needsFullScopeChain) { |
| 1277 emitOpcode(op_tear_off_activation); | 1295 emitOpcode(op_tear_off_activation); |
| 1278 instructions().append(m_activationRegisterIndex); | 1296 instructions().append(m_activationRegisterIndex); |
| 1279 } else if (m_codeBlock->usesArguments && m_codeBlock->numParameters > 1) | 1297 } else if (m_codeBlock->usesArguments && m_codeBlock->numParameters > 1) |
| 1280 emitOpcode(op_tear_off_arguments); | 1298 emitOpcode(op_tear_off_arguments); |
| 1281 | 1299 |
| 1282 return emitUnaryNoDstOp(op_ret, src); | 1300 return emitUnaryNoDstOp(op_ret, src); |
| 1283 } | 1301 } |
| 1284 | 1302 |
| 1285 RegisterID* CodeGenerator::emitUnaryNoDstOp(OpcodeID opcode, RegisterID* src) | 1303 RegisterID* CodeGenerator::emitUnaryNoDstOp(OpcodeID opcode, RegisterID* src) |
| 1286 { | 1304 { |
| 1287 emitOpcode(opcode); | 1305 emitOpcode(opcode); |
| 1288 instructions().append(src->index()); | 1306 instructions().append(src->index()); |
| 1289 return src; | 1307 return src; |
| 1290 } | 1308 } |
| 1291 | 1309 |
| 1292 RegisterID* CodeGenerator::emitConstruct(RegisterID* dst, RegisterID* func, Argu
mentsNode* argumentsNode, unsigned divot, unsigned startOffset, unsigned endOffs
et) | 1310 RegisterID* CodeGenerator::emitConstruct(RegisterID* dst, RegisterID* func, Argu
mentsNode* argumentsNode, unsigned divot, unsigned startOffset, unsigned endOffs
et) |
| 1293 { | 1311 { |
| 1294 ASSERT(func->refCount()); | 1312 ASSERT(func->refCount()); |
| 1295 | 1313 |
| 1314 if (m_shouldEmitProfileHooks) { |
| 1315 // If codegen decided to recycle func as this call's destination registe
r, |
| 1316 // we need to undo that optimization here so that func will still be aro
und |
| 1317 // for the sake of op_profile_did_call. |
| 1318 if (dst == func) { |
| 1319 RefPtr<RegisterID> movedFunc = emitMove(newTemporary(), func); |
| 1320 func = movedFunc.release().releaseRef(); |
| 1321 } |
| 1322 } |
| 1323 |
| 1296 RefPtr<RegisterID> funcProto = newTemporary(); | 1324 RefPtr<RegisterID> funcProto = newTemporary(); |
| 1297 | 1325 |
| 1298 // Generate code for arguments. | 1326 // Generate code for arguments. |
| 1299 Vector<RefPtr<RegisterID>, 16> argv; | 1327 Vector<RefPtr<RegisterID>, 16> argv; |
| 1300 argv.append(newTemporary()); // reserve space for "this" | 1328 argv.append(newTemporary()); // reserve space for "this" |
| 1301 for (ArgumentListNode* n = argumentsNode ? argumentsNode->m_listNode.get() :
0; n; n = n->m_next.get()) { | 1329 for (ArgumentListNode* n = argumentsNode ? argumentsNode->m_listNode.get() :
0; n; n = n->m_next.get()) { |
| 1302 argv.append(newTemporary()); | 1330 argv.append(newTemporary()); |
| 1303 emitNode(argv.last().get(), n); | 1331 emitNode(argv.last().get(), n); |
| 1304 } | 1332 } |
| 1305 | 1333 |
| 1306 if (m_shouldEmitProfileHooks) { | 1334 if (m_shouldEmitProfileHooks) { |
| 1307 emitOpcode(op_profile_will_call); | 1335 emitOpcode(op_profile_will_call); |
| 1308 instructions().append(func->index()); | 1336 instructions().append(func->index()); |
| 1309 } | 1337 } |
| 1310 | 1338 |
| 1311 // Load prototype. | 1339 // Load prototype. |
| 1312 emitExpressionInfo(divot, startOffset, endOffset); | 1340 emitExpressionInfo(divot, startOffset, endOffset); |
| 1313 emitGetById(funcProto.get(), func, globalData()->propertyNames->prototype); | 1341 emitGetById(funcProto.get(), func, globalData()->propertyNames->prototype); |
| 1314 | 1342 |
| 1315 // Reserve space for call frame. | 1343 // Reserve space for call frame. |
| 1316 Vector<RefPtr<RegisterID>, RegisterFile::CallFrameHeaderSize> callFrame; | 1344 Vector<RefPtr<RegisterID>, RegisterFile::CallFrameHeaderSize> callFrame; |
| 1317 for (int i = 0; i < RegisterFile::CallFrameHeaderSize; ++i) | 1345 for (int i = 0; i < RegisterFile::CallFrameHeaderSize; ++i) |
| 1318 callFrame.append(newTemporary()); | 1346 callFrame.append(newTemporary()); |
| 1319 | 1347 |
| 1320 emitExpressionInfo(divot, startOffset, endOffset); | 1348 emitExpressionInfo(divot, startOffset, endOffset); |
| 1321 m_codeBlock->callLinkInfos.append(CallLinkInfo()); | 1349 m_codeBlock->callLinkInfos.append(CallLinkInfo()); |
| 1350 |
| 1322 emitOpcode(op_construct); | 1351 emitOpcode(op_construct); |
| 1323 instructions().append(dst->index()); | 1352 instructions().append(dst->index()); // dst |
| 1324 instructions().append(func->index()); | 1353 instructions().append(func->index()); // func |
| 1325 instructions().append(funcProto->index()); | 1354 instructions().append(argv.size()); // argCount |
| 1326 instructions().append(argv[0]->index()); // argv | |
| 1327 instructions().append(argv.size()); // argc | |
| 1328 instructions().append(argv[0]->index() + argv.size() + RegisterFile::CallFra
meHeaderSize); // registerOffset | 1355 instructions().append(argv[0]->index() + argv.size() + RegisterFile::CallFra
meHeaderSize); // registerOffset |
| 1356 instructions().append(funcProto->index()); // proto |
| 1357 instructions().append(argv[0]->index()); // thisRegister |
| 1329 | 1358 |
| 1330 emitOpcode(op_construct_verify); | 1359 emitOpcode(op_construct_verify); |
| 1331 instructions().append(dst->index()); | 1360 instructions().append(dst->index()); |
| 1332 instructions().append(argv[0]->index()); | 1361 instructions().append(argv[0]->index()); |
| 1333 | 1362 |
| 1334 if (m_shouldEmitProfileHooks) { | 1363 if (m_shouldEmitProfileHooks) { |
| 1335 emitOpcode(op_profile_did_call); | 1364 emitOpcode(op_profile_did_call); |
| 1336 instructions().append(func->index()); | 1365 instructions().append(func->index()); |
| 1366 |
| 1367 if (dst == func) |
| 1368 func->deref(); |
| 1337 } | 1369 } |
| 1338 | 1370 |
| 1339 return dst; | 1371 return dst; |
| 1340 } | 1372 } |
| 1341 | 1373 |
| 1342 RegisterID* CodeGenerator::emitPushScope(RegisterID* scope) | 1374 RegisterID* CodeGenerator::emitPushScope(RegisterID* scope) |
| 1343 { | 1375 { |
| 1344 ControlFlowContext context; | 1376 ControlFlowContext context; |
| 1345 context.isFinallyBlock = false; | 1377 context.isFinallyBlock = false; |
| 1346 m_scopeContextStack.append(context); | 1378 m_scopeContextStack.append(context); |
| (...skipping 359 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1706 // And we could make the caller pass the node pointer in, if there was some
way of getting | 1738 // And we could make the caller pass the node pointer in, if there was some
way of getting |
| 1707 // that from an arbitrary node. However, calling emitExpressionInfo without
any useful data | 1739 // that from an arbitrary node. However, calling emitExpressionInfo without
any useful data |
| 1708 // is still good enough to get us an accurate line number. | 1740 // is still good enough to get us an accurate line number. |
| 1709 emitExpressionInfo(0, 0, 0); | 1741 emitExpressionInfo(0, 0, 0); |
| 1710 RegisterID* exception = emitNewError(newTemporary(), SyntaxError, jsString(g
lobalData(), "Expression too deep")); | 1742 RegisterID* exception = emitNewError(newTemporary(), SyntaxError, jsString(g
lobalData(), "Expression too deep")); |
| 1711 emitThrow(exception); | 1743 emitThrow(exception); |
| 1712 return exception; | 1744 return exception; |
| 1713 } | 1745 } |
| 1714 | 1746 |
| 1715 } // namespace JSC | 1747 } // namespace JSC |
| OLD | NEW |