|
Lines 468-484
macro valueProfile(value, operand, scrat
Source/JavaScriptCore/llint/LowLevelInterpreter64.asm_sec1
|
| 468 |
storeq value, ValueProfile::m_buckets[scratch] |
468 |
storeq value, ValueProfile::m_buckets[scratch] |
| 469 |
end |
469 |
end |
| 470 |
|
470 |
|
| 471 |
macro loadStructure(cell, structure) |
471 |
macro structureIDToStructureWithScratch(structureID, structure, scratch) |
| 472 |
end |
|
|
| 473 |
|
| 474 |
macro loadStructureWithScratch(cell, structure, scratch) |
| 475 |
loadp CodeBlock[cfr], scratch |
472 |
loadp CodeBlock[cfr], scratch |
| 476 |
loadp CodeBlock::m_vm[scratch], scratch |
473 |
loadp CodeBlock::m_vm[scratch], scratch |
| 477 |
loadp VM::heap + Heap::m_structureIDTable + StructureIDTable::m_table[scratch], scratch |
474 |
loadp VM::heap + Heap::m_structureIDTable + StructureIDTable::m_table[scratch], scratch |
| 478 |
loadi JSCell::m_structureID[cell], structure |
475 |
loadi structureID, structure |
| 479 |
loadp [scratch, structure, 8], structure |
476 |
loadp [scratch, structure, 8], structure |
| 480 |
end |
477 |
end |
| 481 |
|
478 |
|
|
|
479 |
macro loadStructureWithScratch(cell, structure, scratch) |
| 480 |
structureIDToStructureWithScratch(JSCell::m_structureID[cell], structure, scratch) |
| 481 |
end |
| 482 |
|
| 482 |
macro loadStructureAndClobberFirstArg(cell, structure) |
483 |
macro loadStructureAndClobberFirstArg(cell, structure) |
| 483 |
loadi JSCell::m_structureID[cell], structure |
484 |
loadi JSCell::m_structureID[cell], structure |
| 484 |
loadp CodeBlock[cfr], cell |
485 |
loadp CodeBlock[cfr], cell |
|
Lines 1204-1244
macro storePropertyAtVariableOffset(prop
Source/JavaScriptCore/llint/LowLevelInterpreter64.asm_sec2
|
| 1204 |
storeq value, (firstOutOfLineOffset - 2) * 8[objectAndStorage, propertyOffsetAsInt, 8] |
1205 |
storeq value, (firstOutOfLineOffset - 2) * 8[objectAndStorage, propertyOffsetAsInt, 8] |
| 1205 |
end |
1206 |
end |
| 1206 |
|
1207 |
|
| 1207 |
macro getById(getPropertyStorage) |
1208 |
_llint_op_get_by_id: |
| 1208 |
traceExecution() |
1209 |
traceExecution() |
| 1209 |
# We only do monomorphic get_by_id caching for now, and we do not modify the |
|
|
| 1210 |
# opcode. We do, however, allow for the cache to change anytime if fails, since |
| 1211 |
# ping-ponging is free. At best we get lucky and the get_by_id will continue |
| 1212 |
# to take fast path on the new cache. At worst we take slow path, which is what |
| 1213 |
# we would have been doing anyway. |
| 1214 |
loadisFromInstruction(2, t0) |
1210 |
loadisFromInstruction(2, t0) |
| 1215 |
loadConstantOrVariableCell(t0, t3, .opGetByIdSlow) |
1211 |
loadConstantOrVariableCell(t0, t3, .opGetByIdSlow) |
| 1216 |
loadStructureWithScratch(t3, t2, t1) |
1212 |
loadi JSCell::m_structureID[t3], t1 |
| 1217 |
loadpFromInstruction(4, t1) |
1213 |
loadisFromInstruction(4, t2) |
| 1218 |
bpneq t2, t1, .opGetByIdSlow |
1214 |
bineq t2, t1, .opGetByIdSlow |
| 1219 |
getPropertyStorage( |
1215 |
loadisFromInstruction(5, t1) |
| 1220 |
t3, |
1216 |
loadisFromInstruction(1, t2) |
| 1221 |
t0, |
1217 |
loadPropertyAtVariableOffset(t1, t3, t0) |
| 1222 |
macro (propertyStorage, scratch) |
1218 |
storeq t0, [cfr, t2, 8] |
| 1223 |
loadisFromInstruction(5, t2) |
1219 |
valueProfile(t0, 8, t1) |
| 1224 |
loadisFromInstruction(1, t1) |
1220 |
dispatch(9) |
| 1225 |
loadq [propertyStorage, t2], scratch |
|
|
| 1226 |
storeq scratch, [cfr, t1, 8] |
| 1227 |
valueProfile(scratch, 8, t1) |
| 1228 |
dispatch(9) |
| 1229 |
end) |
| 1230 |
|
| 1231 |
.opGetByIdSlow: |
| 1232 |
callSlowPath(_llint_slow_path_get_by_id) |
| 1233 |
dispatch(9) |
| 1234 |
end |
| 1235 |
|
| 1236 |
_llint_op_get_by_id: |
| 1237 |
getById(withInlineStorage) |
| 1238 |
|
| 1239 |
|
1221 |
|
| 1240 |
_llint_op_get_by_id_out_of_line: |
1222 |
.opGetByIdSlow: |
| 1241 |
getById(withOutOfLineStorage) |
1223 |
callSlowPath(_llint_slow_path_get_by_id) |
|
|
1224 |
dispatch(9) |
| 1242 |
|
1225 |
|
| 1243 |
|
1226 |
|
| 1244 |
_llint_op_get_array_length: |
1227 |
_llint_op_get_array_length: |
|
Lines 1264-1360
_llint_op_get_array_length:
Source/JavaScriptCore/llint/LowLevelInterpreter64.asm_sec3
|
| 1264 |
dispatch(9) |
1247 |
dispatch(9) |
| 1265 |
|
1248 |
|
| 1266 |
|
1249 |
|
| 1267 |
macro putById(getPropertyStorage) |
1250 |
_llint_op_put_by_id: |
| 1268 |
traceExecution() |
1251 |
traceExecution() |
| 1269 |
writeBarrierOnOperands(1, 3) |
1252 |
writeBarrierOnOperands(1, 3) |
| 1270 |
loadisFromInstruction(1, t3) |
1253 |
loadisFromInstruction(1, t3) |
| 1271 |
loadConstantOrVariableCell(t3, t0, .opPutByIdSlow) |
1254 |
loadConstantOrVariableCell(t3, t0, .opPutByIdSlow) |
| 1272 |
loadStructureWithScratch(t0, t2, t1) |
1255 |
loadi JSCell::m_structureID[t0], t2 |
| 1273 |
loadpFromInstruction(4, t1) |
1256 |
loadisFromInstruction(4, t1) |
| 1274 |
bpneq t2, t1, .opPutByIdSlow |
1257 |
bineq t2, t1, .opPutByIdSlow |
| 1275 |
getPropertyStorage( |
1258 |
|
| 1276 |
t0, |
1259 |
# At this point, we have: |
| 1277 |
t3, |
1260 |
# t1, t2 -> current structure ID |
| 1278 |
macro (propertyStorage, scratch) |
1261 |
# t0 -> object base |
| 1279 |
loadisFromInstruction(5, t1) |
|
|
| 1280 |
loadisFromInstruction(3, t2) |
| 1281 |
loadConstantOrVariable(t2, scratch) |
| 1282 |
storeq scratch, [propertyStorage, t1] |
| 1283 |
dispatch(9) |
| 1284 |
end) |
| 1285 |
end |
| 1286 |
|
| 1287 |
_llint_op_put_by_id: |
| 1288 |
putById(withInlineStorage) |
| 1289 |
|
1262 |
|
| 1290 |
.opPutByIdSlow: |
1263 |
loadisFromInstruction(6, t1) |
| 1291 |
callSlowPath(_llint_slow_path_put_by_id) |
1264 |
|
| 1292 |
dispatch(9) |
1265 |
btiz t1, .opPutByIdNotTransition |
| 1293 |
|
1266 |
|
|
|
1267 |
# This is the transition case. t1 holds the new structureID. t2 holds the old structure ID. |
| 1268 |
# If we have a chain, we need to check it. t0 is the base. We may clobber t1 to use it as |
| 1269 |
# scratch. |
| 1270 |
loadpFromInstruction(7, t3) |
| 1271 |
btpz t3, .opPutByIdTransitionDirect |
| 1272 |
|
| 1273 |
loadp StructureChain::m_vector[t3], t3 |
| 1274 |
assert(macro (ok) btpnz t3, ok end) |
| 1275 |
|
| 1276 |
structureIDToStructureWithScratch(t2, t2, t1) |
| 1277 |
loadq Structure::m_prototype[t2], t2 |
| 1278 |
bqeq t2, ValueNull, .opPutByIdTransitionChainDone |
| 1279 |
.opPutByIdTransitionChainLoop: |
| 1280 |
loadStructureAndClobberFirstArg(t2, t1) |
| 1281 |
move t1, t2 |
| 1282 |
bpneq t2, [t3], .opPutByIdSlot |
| 1283 |
addp 8, t3 |
| 1284 |
loadq Structure::m_prototype[t2], t2 |
| 1285 |
bqneq t2, ValueNull, .opPutByIdTransitionChainLoop |
| 1294 |
|
1286 |
|
| 1295 |
_llint_op_put_by_id_out_of_line: |
1287 |
.opPutByIdTransitionChainDone: |
| 1296 |
putById(withOutOfLineStorage) |
1288 |
# Reload the new structure, since we clobbered it above. |
|
|
1289 |
loadisFromInstruction(6, t1) |
| 1297 |
|
1290 |
|
|
|
1291 |
.opPutByIdTransitionDirect: |
| 1292 |
storei t1, JSCell::m_structureID[t0] |
| 1298 |
|
1293 |
|
| 1299 |
macro putByIdTransition(additionalChecks, getPropertyStorage) |
1294 |
.opPutByIdNotTransition: |
| 1300 |
traceExecution() |
1295 |
# The only thing live right now is t0, which holds the base. |
| 1301 |
writeBarrierOnOperand(1) |
1296 |
loadisFromInstruction(3, t1) |
| 1302 |
loadisFromInstruction(1, t3) |
1297 |
loadConstantOrVariable(t1, t2) |
| 1303 |
loadpFromInstruction(4, t1) |
|
|
| 1304 |
loadConstantOrVariableCell(t3, t0, .opPutByIdSlow) |
| 1305 |
loadStructureWithScratch(t0, t2, t3) |
| 1306 |
bpneq t2, t1, .opPutByIdSlow |
| 1307 |
additionalChecks(t1, t3, t2) |
| 1308 |
loadisFromInstruction(3, t2) |
| 1309 |
loadisFromInstruction(5, t1) |
1298 |
loadisFromInstruction(5, t1) |
| 1310 |
getPropertyStorage( |
1299 |
storePropertyAtVariableOffset(t1, t0, t2) |
| 1311 |
t0, |
1300 |
dispatch(9) |
| 1312 |
t3, |
|
|
| 1313 |
macro (propertyStorage, scratch) |
| 1314 |
addp t1, propertyStorage, t3 |
| 1315 |
loadConstantOrVariable(t2, t1) |
| 1316 |
storeq t1, [t3] |
| 1317 |
loadpFromInstruction(6, t1) |
| 1318 |
loadi Structure::m_blob + StructureIDBlob::u.words.word1[t1], t1 |
| 1319 |
storei t1, JSCell::m_structureID[t0] |
| 1320 |
dispatch(9) |
| 1321 |
end) |
| 1322 |
end |
| 1323 |
|
| 1324 |
macro noAdditionalChecks(oldStructure, scratch, scratch2) |
| 1325 |
end |
| 1326 |
|
| 1327 |
macro structureChainChecks(oldStructure, scratch, scratch2) |
| 1328 |
const protoCell = oldStructure # Reusing the oldStructure register for the proto |
| 1329 |
loadpFromInstruction(7, scratch) |
| 1330 |
assert(macro (ok) btpnz scratch, ok end) |
| 1331 |
loadp StructureChain::m_vector[scratch], scratch |
| 1332 |
assert(macro (ok) btpnz scratch, ok end) |
| 1333 |
bqeq Structure::m_prototype[oldStructure], ValueNull, .done |
| 1334 |
.loop: |
| 1335 |
loadq Structure::m_prototype[oldStructure], protoCell |
| 1336 |
loadStructureAndClobberFirstArg(protoCell, scratch2) |
| 1337 |
move scratch2, oldStructure |
| 1338 |
bpneq oldStructure, [scratch], .opPutByIdSlow |
| 1339 |
addp 8, scratch |
| 1340 |
bqneq Structure::m_prototype[oldStructure], ValueNull, .loop |
| 1341 |
.done: |
| 1342 |
end |
| 1343 |
|
| 1344 |
_llint_op_put_by_id_transition_direct: |
| 1345 |
putByIdTransition(noAdditionalChecks, withInlineStorage) |
| 1346 |
|
| 1347 |
|
| 1348 |
_llint_op_put_by_id_transition_direct_out_of_line: |
| 1349 |
putByIdTransition(noAdditionalChecks, withOutOfLineStorage) |
| 1350 |
|
| 1351 |
|
| 1352 |
_llint_op_put_by_id_transition_normal: |
| 1353 |
putByIdTransition(structureChainChecks, withInlineStorage) |
| 1354 |
|
| 1355 |
|
1301 |
|
| 1356 |
_llint_op_put_by_id_transition_normal_out_of_line: |
1302 |
.opPutByIdSlow: |
| 1357 |
putByIdTransition(structureChainChecks, withOutOfLineStorage) |
1303 |
callSlowPath(_llint_slow_path_put_by_id) |
|
|
1304 |
dispatch(9) |
| 1358 |
|
1305 |
|
| 1359 |
|
1306 |
|
| 1360 |
_llint_op_get_by_val: |
1307 |
_llint_op_get_by_val: |