@@ -345,7 +345,7 @@ void Rewriter::emitGuardJump(bool useJne) {
345345 }
346346 }
347347
348- if (allArgsInPlace) {
348+ if (allArgsInPlace && !should_use_second_guard_destination ) {
349349 if (useJne) {
350350 assembler->jne (assembler::JumpDestination::fromStart (rewrite->getSlotSize ()));
351351 } else {
@@ -358,6 +358,9 @@ void Rewriter::emitGuardJump(bool useJne) {
358358 assembler->je (assembler::JumpDestination::fromStart ((1 << 31 ) - 2 ));
359359 }
360360
361+ if (should_use_second_guard_destination) {
362+ assert (marked_inside_ic);
363+ }
361364 guard_infos.emplace_back (assembler->curInstPointer (), VarLocations (args));
362365 }
363366
@@ -366,15 +369,39 @@ void Rewriter::emitGuardJump(bool useJne) {
366369 }
367370}
368371
369- void Rewriter::guardCalls () {
372+ void Rewriter::guardCalls (int continue_offset ) {
370373 for (GuardInfo& guard_info : guard_infos) {
374+ assembler->comment (" path for guard fail" );
375+
371376 uint8_t * dest_addr = assembler->curInstPointer ();
372377 int offset = dest_addr - guard_info.guard_jmp_addr ;
373378 *((int *)(guard_info.guard_jmp_addr - 4 )) = offset;
374379
375380 guard_info.var_locations .arrangeAsArgs (this );
376381
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+ }
378405 }
379406}
380407
@@ -1134,6 +1161,10 @@ void Rewriter::commit() {
11341161
11351162 // Now, start emitting assembly; check if we're dong guarding after each.
11361163 for (int i = 0 ; i < actions.size (); i++) {
1164+ if (second_slowpath && i == action_where_second_slowpath_starts) {
1165+ this ->useSecondGuardDestination ();
1166+ }
1167+
11371168 actions[i].action ();
11381169
11391170 if (failed) {
@@ -1310,7 +1341,7 @@ bool Rewriter::finishAssembly(int continue_offset) {
13101341
13111342 assembler->jmp (assembler::JumpDestination::fromStart (continue_offset));
13121343
1313- guardCalls ();
1344+ guardCalls (continue_offset );
13141345
13151346 assembler->fillWithNops ();
13161347
@@ -1763,6 +1794,9 @@ Rewriter::Rewriter(std::unique_ptr<ICSlotRewrite> rewrite, int num_args, const L
17631794 const_loader(this ),
17641795 return_location(this ->rewrite->returnRegister ()),
17651796 failed(false ),
1797+ second_slowpath(NULL ),
1798+ action_where_second_slowpath_starts(-1 ),
1799+ should_use_second_guard_destination(false ),
17661800 added_changing_action(false ),
17671801 marked_inside_ic(false ) {
17681802 initPhaseCollecting ();
@@ -1775,7 +1809,6 @@ Rewriter::Rewriter(std::unique_ptr<ICSlotRewrite> rewrite, int num_args, const L
17751809 addLocationToVar (var, l);
17761810
17771811 var->is_arg = true ;
1778- var->arg_loc = l;
17791812
17801813 args.push_back (var);
17811814 }
@@ -2138,24 +2171,26 @@ void VarLocations::arrangeAsArgs(Rewriter* rewriter) {
21382171
21392172 for (int i = 0 ; i < vars.size (); i++) {
21402173 Location targetLoc = Location::forArg (i);
2141- Location startLoc = Location::any ();
2142- assert (this ->vars [i].second .size ());
2174+ Location startLoc = Location::none ();
21432175 for (Location l : this ->vars [i].second ) {
21442176 if (l == targetLoc) {
21452177 startLoc = l;
21462178 break ;
21472179 } else if (l.type == Location::Register) {
21482180 startLoc = l;
21492181 } else {
2150- if (startLoc == Location::any ()) {
2182+ if (startLoc == Location::none ()) {
21512183 startLoc = l;
21522184 }
21532185 }
21542186 }
2155- assert (startLoc != Location::any ());
21562187 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 );
21592194 }
21602195 }
21612196
@@ -2170,6 +2205,9 @@ void VarLocations::arrangeAsArgs(Rewriter* rewriter) {
21702205 };
21712206
21722207 for (int i = vars.size () - 1 ; i >= 0 ; i--) {
2208+ if (vars[i].first ->is_constant )
2209+ continue ;
2210+
21732211 Location curLoc = locs[i];
21742212 Location targetLoc = Location::forArg (i);
21752213 if (curLoc == targetLoc) continue ;
@@ -2182,7 +2220,7 @@ void VarLocations::arrangeAsArgs(Rewriter* rewriter) {
21822220 assembler::Register r = getFreeReg ();
21832221 assert (curLoc.type == Location::Scratch);
21842222 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 ));
21862224 locs[i] = targetLoc;
21872225 }
21882226 } else {
@@ -2193,17 +2231,32 @@ void VarLocations::arrangeAsArgs(Rewriter* rewriter) {
21932231 argInReg[targetLoc.asRegister ().regnum ] = -1 ;
21942232 locs[argInReg[r.regnum ]] = r;
21952233 }
2234+
21962235 if (curLoc.type == Location::Register) {
21972236 assembler->mov (curLoc.asRegister (), targetLoc.asRegister ());
21982237 argInReg[curLoc.asRegister ().regnum ] = -1 ;
21992238 } else {
22002239 assert (curLoc.type == Location::Scratch);
22012240 assembler->mov (assembler::Indirect (assembler::RSP, rewriter->rewrite ->getScratchRspOffset () + curLoc.scratch_offset ), targetLoc.asRegister ());
22022241 }
2242+
22032243 locs[i] = targetLoc;
22042244 argInReg[targetLoc.asRegister ().regnum ] = i;
22052245 }
22062246 }
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+ }
22072260}
22082261
22092262}
0 commit comments