@@ -345,7 +345,7 @@ void Rewriter::emitGuardJump(bool useJne) {
345
345
}
346
346
}
347
347
348
- if (allArgsInPlace) {
348
+ if (allArgsInPlace && !should_use_second_guard_destination ) {
349
349
if (useJne) {
350
350
assembler->jne (assembler::JumpDestination::fromStart (rewrite->getSlotSize ()));
351
351
} else {
@@ -358,6 +358,9 @@ void Rewriter::emitGuardJump(bool useJne) {
358
358
assembler->je (assembler::JumpDestination::fromStart ((1 << 31 ) - 2 ));
359
359
}
360
360
361
+ if (should_use_second_guard_destination) {
362
+ assert (marked_inside_ic);
363
+ }
361
364
guard_infos.emplace_back (assembler->curInstPointer (), VarLocations (args));
362
365
}
363
366
@@ -366,15 +369,39 @@ void Rewriter::emitGuardJump(bool useJne) {
366
369
}
367
370
}
368
371
369
- void Rewriter::guardCalls () {
372
+ void Rewriter::guardCalls (int continue_offset ) {
370
373
for (GuardInfo& guard_info : guard_infos) {
374
+ assembler->comment (" path for guard fail" );
375
+
371
376
uint8_t * dest_addr = assembler->curInstPointer ();
372
377
int offset = dest_addr - guard_info.guard_jmp_addr ;
373
378
*((int *)(guard_info.guard_jmp_addr - 4 )) = offset;
374
379
375
380
guard_info.var_locations .arrangeAsArgs (this );
376
381
377
- assembler->jmp (assembler::JumpDestination::fromStart (rewrite->getSlotSize ()));
382
+ if (!should_use_second_guard_destination) {
383
+ assembler->jmp (assembler::JumpDestination::fromStart (rewrite->getSlotSize ()));
384
+ } else {
385
+ assembler->comment (" calling second slowpath" );
386
+
387
+ // TODO Inefficient way to write a call
388
+ assembler::Register r = allocReg (assembler::R11);
389
+ assembler->mov (assembler::Immediate (second_slowpath), r);
390
+ assembler->callq (r);
391
+
392
+ assembler->comment (" mark inside ic" );
393
+
394
+ uintptr_t counter_addr = (uintptr_t )(&picked_slot->num_inside );
395
+ if (isLargeConstant (counter_addr)) {
396
+ assembler::Register reg = assembler::R11;
397
+ assembler->mov (assembler::Immediate (counter_addr), reg);
398
+ assembler->decl (assembler::Indirect (reg, 0 ));
399
+ } else {
400
+ assembler->decl (assembler::Immediate (counter_addr));
401
+ }
402
+
403
+ assembler->jmp (assembler::JumpDestination::fromStart (continue_offset));
404
+ }
378
405
}
379
406
}
380
407
@@ -1134,6 +1161,10 @@ void Rewriter::commit() {
1134
1161
1135
1162
// Now, start emitting assembly; check if we're dong guarding after each.
1136
1163
for (int i = 0 ; i < actions.size (); i++) {
1164
+ if (second_slowpath && i == action_where_second_slowpath_starts) {
1165
+ this ->useSecondGuardDestination ();
1166
+ }
1167
+
1137
1168
actions[i].action ();
1138
1169
1139
1170
if (failed) {
@@ -1310,7 +1341,7 @@ bool Rewriter::finishAssembly(int continue_offset) {
1310
1341
1311
1342
assembler->jmp (assembler::JumpDestination::fromStart (continue_offset));
1312
1343
1313
- guardCalls ();
1344
+ guardCalls (continue_offset );
1314
1345
1315
1346
assembler->fillWithNops ();
1316
1347
@@ -1763,6 +1794,9 @@ Rewriter::Rewriter(std::unique_ptr<ICSlotRewrite> rewrite, int num_args, const L
1763
1794
const_loader(this ),
1764
1795
return_location(this ->rewrite->returnRegister ()),
1765
1796
failed(false ),
1797
+ second_slowpath(NULL ),
1798
+ action_where_second_slowpath_starts(-1 ),
1799
+ should_use_second_guard_destination(false ),
1766
1800
added_changing_action(false ),
1767
1801
marked_inside_ic(false ) {
1768
1802
initPhaseCollecting ();
@@ -1775,7 +1809,6 @@ Rewriter::Rewriter(std::unique_ptr<ICSlotRewrite> rewrite, int num_args, const L
1775
1809
addLocationToVar (var, l);
1776
1810
1777
1811
var->is_arg = true ;
1778
- var->arg_loc = l;
1779
1812
1780
1813
args.push_back (var);
1781
1814
}
@@ -2138,24 +2171,26 @@ void VarLocations::arrangeAsArgs(Rewriter* rewriter) {
2138
2171
2139
2172
for (int i = 0 ; i < vars.size (); i++) {
2140
2173
Location targetLoc = Location::forArg (i);
2141
- Location startLoc = Location::any ();
2142
- assert (this ->vars [i].second .size ());
2174
+ Location startLoc = Location::none ();
2143
2175
for (Location l : this ->vars [i].second ) {
2144
2176
if (l == targetLoc) {
2145
2177
startLoc = l;
2146
2178
break ;
2147
2179
} else if (l.type == Location::Register) {
2148
2180
startLoc = l;
2149
2181
} else {
2150
- if (startLoc == Location::any ()) {
2182
+ if (startLoc == Location::none ()) {
2151
2183
startLoc = l;
2152
2184
}
2153
2185
}
2154
2186
}
2155
- assert (startLoc != Location::any ());
2156
2187
locs.push_back (startLoc);
2157
- if (startLoc.type == Location::Register) {
2158
- argInReg[startLoc.asRegister ().regnum ] = i;
2188
+ if (startLoc != Location::none ()) {
2189
+ if (startLoc.type == Location::Register) {
2190
+ argInReg[startLoc.asRegister ().regnum ] = i;
2191
+ }
2192
+ } else {
2193
+ assert (this ->vars [i].first ->is_constant );
2159
2194
}
2160
2195
}
2161
2196
@@ -2170,6 +2205,9 @@ void VarLocations::arrangeAsArgs(Rewriter* rewriter) {
2170
2205
};
2171
2206
2172
2207
for (int i = vars.size () - 1 ; i >= 0 ; i--) {
2208
+ if (vars[i].first ->is_constant )
2209
+ continue ;
2210
+
2173
2211
Location curLoc = locs[i];
2174
2212
Location targetLoc = Location::forArg (i);
2175
2213
if (curLoc == targetLoc) continue ;
@@ -2182,7 +2220,7 @@ void VarLocations::arrangeAsArgs(Rewriter* rewriter) {
2182
2220
assembler::Register r = getFreeReg ();
2183
2221
assert (curLoc.type == Location::Scratch);
2184
2222
assembler->mov (assembler::Indirect (assembler::RSP, rewriter->rewrite ->getScratchRspOffset () + curLoc.scratch_offset ), r);
2185
- assembler->mov (r, assembler::Indirect (assembler::RSP, curLoc .stack_offset ));
2223
+ assembler->mov (r, assembler::Indirect (assembler::RSP, targetLoc .stack_offset ));
2186
2224
locs[i] = targetLoc;
2187
2225
}
2188
2226
} else {
@@ -2193,17 +2231,32 @@ void VarLocations::arrangeAsArgs(Rewriter* rewriter) {
2193
2231
argInReg[targetLoc.asRegister ().regnum ] = -1 ;
2194
2232
locs[argInReg[r.regnum ]] = r;
2195
2233
}
2234
+
2196
2235
if (curLoc.type == Location::Register) {
2197
2236
assembler->mov (curLoc.asRegister (), targetLoc.asRegister ());
2198
2237
argInReg[curLoc.asRegister ().regnum ] = -1 ;
2199
2238
} else {
2200
2239
assert (curLoc.type == Location::Scratch);
2201
2240
assembler->mov (assembler::Indirect (assembler::RSP, rewriter->rewrite ->getScratchRspOffset () + curLoc.scratch_offset ), targetLoc.asRegister ());
2202
2241
}
2242
+
2203
2243
locs[i] = targetLoc;
2204
2244
argInReg[targetLoc.asRegister ().regnum ] = i;
2205
2245
}
2206
2246
}
2247
+
2248
+ for (int i = vars.size () - 1 ; i >= 0 ; i--) {
2249
+ if (vars[i].first ->is_constant ) {
2250
+ Location targetLoc = Location::forArg (i);
2251
+ if (targetLoc.type == Location::Register) {
2252
+ assembler->mov (assembler::Immediate (vars[i].first ->constant_value ), targetLoc.asRegister ());
2253
+ } else {
2254
+ // TODO inefficient
2255
+ assembler->mov (assembler::Immediate (vars[i].first ->constant_value ), assembler::R11);
2256
+ assembler->mov (assembler::R11, assembler::Indirect (assembler::RSP, targetLoc.stack_offset ));
2257
+ }
2258
+ }
2259
+ }
2207
2260
}
2208
2261
2209
2262
}
0 commit comments