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 |