Chromium Code Reviews| Index: src/ia32/lithium-codegen-ia32.cc |
| diff --git a/src/ia32/lithium-codegen-ia32.cc b/src/ia32/lithium-codegen-ia32.cc |
| index 50ed1048ba94343f0e8dac9d1e51c1c9327f4a0e..4c9c8e30717c12244cae568b4e4ae29f4971fe5d 100644 |
| --- a/src/ia32/lithium-codegen-ia32.cc |
| +++ b/src/ia32/lithium-codegen-ia32.cc |
| @@ -157,6 +157,8 @@ bool LCodeGen::GeneratePrologue() { |
| // Trace the call. |
| if (FLAG_trace) { |
| + // We have not executed any compiled code yet, so esi still holds the |
| + // incoming context. |
| __ CallRuntime(Runtime::kTraceEnter, 0); |
| } |
| return !is_aborted(); |
| @@ -367,10 +369,14 @@ void LCodeGen::AddToTranslation(Translation* translation, |
| void LCodeGen::CallCode(Handle<Code> code, |
| RelocInfo::Mode mode, |
| - LInstruction* instr) { |
| + LInstruction* instr, |
| + bool adjusted) { |
| ASSERT(instr != NULL); |
| LPointerMap* pointers = instr->pointer_map(); |
| RecordPosition(pointers->position()); |
| + if (!adjusted) { |
|
fschneider
2011/02/09 13:41:53
Is there a convenient way to assert that
"!adjus
|
| + __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); |
| + } |
| __ call(code, mode); |
| RegisterLazyDeoptimization(instr); |
| @@ -383,15 +389,19 @@ void LCodeGen::CallCode(Handle<Code> code, |
| } |
| -void LCodeGen::CallRuntime(Runtime::Function* function, |
| - int num_arguments, |
| - LInstruction* instr) { |
| +void LCodeGen::CallRuntime(Runtime::Function* fun, |
| + int argc, |
| + LInstruction* instr, |
| + bool adjusted) { |
| ASSERT(instr != NULL); |
| ASSERT(instr->HasPointerMap()); |
| LPointerMap* pointers = instr->pointer_map(); |
| RecordPosition(pointers->position()); |
| - __ CallRuntime(function, num_arguments); |
| + if (!adjusted) { |
| + __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); |
| + } |
| + __ CallRuntime(fun, argc); |
| RegisterLazyDeoptimization(instr); |
| } |
| @@ -568,10 +578,6 @@ void LCodeGen::RecordSafepoint( |
| safepoint.DefinePointerRegister(ToRegister(pointer)); |
| } |
| } |
| - if (kind & Safepoint::kWithRegisters) { |
| - // Register esi always contains a pointer to the context. |
| - safepoint.DefinePointerRegister(esi); |
| - } |
| } |
| @@ -635,6 +641,7 @@ void LCodeGen::DoParameter(LParameter* instr) { |
| void LCodeGen::DoCallStub(LCallStub* instr) { |
| + ASSERT(ToRegister(instr->context()).is(esi)); |
| ASSERT(ToRegister(instr->result()).is(eax)); |
| switch (instr->hydrogen()->major_key()) { |
| case CodeStub::RegExpConstructResult: { |
| @@ -1011,7 +1018,7 @@ void LCodeGen::DoBitNotI(LBitNotI* instr) { |
| void LCodeGen::DoThrow(LThrow* instr) { |
| __ push(ToOperand(instr->InputAt(0))); |
| - CallRuntime(Runtime::kThrow, 1, instr); |
| + CallRuntime(Runtime::kThrow, 1, instr, false); |
| if (FLAG_debug_code) { |
| Comment("Unreachable code."); |
| @@ -1083,7 +1090,7 @@ void LCodeGen::DoArithmeticT(LArithmeticT* instr) { |
| ASSERT(ToRegister(instr->result()).is(eax)); |
| TypeRecordingBinaryOpStub stub(instr->op(), NO_OVERWRITE); |
| - CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); |
| + CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr, false); |
| } |
| @@ -1196,6 +1203,7 @@ void LCodeGen::EmitGoto(int block, LDeferredCode* deferred_stack_check) { |
| void LCodeGen::DoDeferredStackCheck(LGoto* instr) { |
| __ pushad(); |
| + __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); |
| __ CallRuntimeSaveDoubles(Runtime::kStackGuard); |
| RecordSafepointWithRegisters( |
| instr->pointer_map(), 0, Safepoint::kNoDeoptimizationIndex); |
| @@ -1686,6 +1694,7 @@ void LCodeGen::DoCmpMapAndBranch(LCmpMapAndBranch* instr) { |
| void LCodeGen::DoInstanceOf(LInstanceOf* instr) { |
| // Object and function are in fixed registers defined by the stub. |
| + ASSERT(ToRegister(instr->context()).is(esi)); |
| InstanceofStub stub(InstanceofStub::kArgsInRegisters); |
| CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); |
| @@ -1701,6 +1710,7 @@ void LCodeGen::DoInstanceOf(LInstanceOf* instr) { |
| void LCodeGen::DoInstanceOfAndBranch(LInstanceOfAndBranch* instr) { |
| + ASSERT(ToRegister(instr->context()).is(esi)); |
| int true_block = chunk_->LookupDestination(instr->true_block_id()); |
| int false_block = chunk_->LookupDestination(instr->false_block_id()); |
| @@ -1794,12 +1804,13 @@ void LCodeGen::DoDeferredLInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr, |
| Register temp = ToRegister(instr->TempAt(0)); |
| ASSERT(temp.is(edi)); |
| __ mov(InstanceofStub::right(), Immediate(instr->function())); |
| - static const int kAdditionalDelta = 13; |
| + static const int kAdditionalDelta = 16; |
| int delta = masm_->SizeOfCodeGeneratedSince(map_check) + kAdditionalDelta; |
| Label before_push_delta; |
| __ bind(&before_push_delta); |
| __ mov(temp, Immediate(delta)); |
| __ mov(Operand(esp, EspIndexForPushAll(temp) * kPointerSize), temp); |
| + __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); |
| __ call(stub.GetCode(), RelocInfo::CODE_TARGET); |
| ASSERT_EQ(kAdditionalDelta, |
| masm_->SizeOfCodeGeneratedSince(&before_push_delta)); |
| @@ -1836,7 +1847,7 @@ void LCodeGen::DoCmpT(LCmpT* instr) { |
| Token::Value op = instr->op(); |
| Handle<Code> ic = CompareIC::GetUninitialized(op); |
| - CallCode(ic, RelocInfo::CODE_TARGET, instr); |
| + CallCode(ic, RelocInfo::CODE_TARGET, instr, false); |
| Condition condition = ComputeCompareCondition(op); |
| if (op == Token::GT || op == Token::LTE) { |
| @@ -1859,7 +1870,7 @@ void LCodeGen::DoCmpTAndBranch(LCmpTAndBranch* instr) { |
| int false_block = chunk_->LookupDestination(instr->false_block_id()); |
| Handle<Code> ic = CompareIC::GetUninitialized(op); |
| - CallCode(ic, RelocInfo::CODE_TARGET, instr); |
| + CallCode(ic, RelocInfo::CODE_TARGET, instr, false); |
| // The compare stub expects compare condition and the input operands |
| // reversed for GT and LTE. |
| @@ -1874,9 +1885,12 @@ void LCodeGen::DoCmpTAndBranch(LCmpTAndBranch* instr) { |
| void LCodeGen::DoReturn(LReturn* instr) { |
| if (FLAG_trace) { |
| - // Preserve the return value on the stack and rely on the runtime |
| - // call to return the value in the same register. |
| + // Preserve the return value on the stack and rely on the runtime call |
| + // to return the value in the same register. We're leaving the code |
| + // managed by the register allocator and tearing down the frame, it's |
| + // safe to write to the context register. |
| __ push(eax); |
| + __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); |
| __ CallRuntime(Runtime::kTraceExit, 1); |
| } |
| __ mov(esp, ebp); |
| @@ -1945,6 +1959,7 @@ void LCodeGen::DoLoadNamedField(LLoadNamedField* instr) { |
| void LCodeGen::DoLoadNamedGeneric(LLoadNamedGeneric* instr) { |
| + ASSERT(ToRegister(instr->context()).is(esi)); |
| ASSERT(ToRegister(instr->object()).is(eax)); |
| ASSERT(ToRegister(instr->result()).is(eax)); |
| @@ -2047,6 +2062,7 @@ void LCodeGen::DoLoadKeyedFastElement(LLoadKeyedFastElement* instr) { |
| void LCodeGen::DoLoadKeyedGeneric(LLoadKeyedGeneric* instr) { |
| + ASSERT(ToRegister(instr->context()).is(esi)); |
| ASSERT(ToRegister(instr->object()).is(edx)); |
| ASSERT(ToRegister(instr->key()).is(eax)); |
| @@ -2115,7 +2131,11 @@ void LCodeGen::DoApplyArguments(LApplyArguments* instr) { |
| __ cmp(receiver, Factory::undefined_value()); |
| __ j(not_equal, &receiver_ok); |
| __ bind(&global_receiver); |
| - __ mov(receiver, GlobalObjectOperand()); |
| + // TODO(kmillikin): We have a hydrogen value for the global object. See |
| + // if it's better to use it than to explicitly fetch it from the context |
| + // here. |
| + __ mov(receiver, Operand(ebp, StandardFrameConstants::kContextOffset)); |
| + __ mov(receiver, ContextOperand(receiver, Context::GLOBAL_INDEX)); |
| __ bind(&receiver_ok); |
| Register length = ToRegister(instr->length()); |
| @@ -2156,9 +2176,6 @@ void LCodeGen::DoApplyArguments(LApplyArguments* instr) { |
| ASSERT(receiver.is(eax)); |
| v8::internal::ParameterCount actual(eax); |
| __ InvokeFunction(edi, actual, CALL_FUNCTION, &safepoint_generator); |
| - |
| - // Restore context. |
| - __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); |
| } |
| @@ -2174,7 +2191,7 @@ void LCodeGen::DoPushArgument(LPushArgument* instr) { |
| void LCodeGen::DoContext(LContext* instr) { |
| Register result = ToRegister(instr->result()); |
| - __ mov(result, esi); |
| + __ mov(result, Operand(ebp, StandardFrameConstants::kContextOffset)); |
| } |
| @@ -2210,6 +2227,8 @@ void LCodeGen::CallKnownFunction(Handle<JSFunction> function, |
| (scope()->num_heap_slots() > 0); |
| if (change_context) { |
| __ mov(esi, FieldOperand(edi, JSFunction::kContextOffset)); |
| + } else { |
| + __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); |
|
fschneider
2011/02/09 15:23:31
Should this function for now also take an addition
|
| } |
| // Set eax to arguments count if adaption is not needed. Assumes that eax |
| @@ -2230,9 +2249,6 @@ void LCodeGen::CallKnownFunction(Handle<JSFunction> function, |
| // Setup deoptimization. |
| RegisterLazyDeoptimization(instr); |
| - |
| - // Restore context. |
| - __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); |
| } |
| @@ -2275,6 +2291,7 @@ void LCodeGen::DoDeferredMathAbsTaggedHeapNumber(LUnaryMathOperation* instr) { |
| // Slow case: Call the runtime system to do the number allocation. |
| __ bind(&slow); |
| + __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); |
| __ CallRuntimeSaveDoubles(Runtime::kAllocateHeapNumber); |
| RecordSafepointWithRegisters( |
| instr->pointer_map(), 0, Safepoint::kNoDeoptimizationIndex); |
| @@ -2486,7 +2503,7 @@ void LCodeGen::DoMathLog(LUnaryMathOperation* instr) { |
| ASSERT(ToDoubleRegister(instr->result()).is(xmm1)); |
| TranscendentalCacheStub stub(TranscendentalCache::LOG, |
| TranscendentalCacheStub::UNTAGGED); |
| - CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); |
| + CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr, false); |
| } |
| @@ -2494,7 +2511,7 @@ void LCodeGen::DoMathCos(LUnaryMathOperation* instr) { |
| ASSERT(ToDoubleRegister(instr->result()).is(xmm1)); |
| TranscendentalCacheStub stub(TranscendentalCache::COS, |
| TranscendentalCacheStub::UNTAGGED); |
| - CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); |
| + CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr, false); |
| } |
| @@ -2502,7 +2519,7 @@ void LCodeGen::DoMathSin(LUnaryMathOperation* instr) { |
| ASSERT(ToDoubleRegister(instr->result()).is(xmm1)); |
| TranscendentalCacheStub stub(TranscendentalCache::SIN, |
| TranscendentalCacheStub::UNTAGGED); |
| - CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); |
| + CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr, false); |
| } |
| @@ -2540,46 +2557,46 @@ void LCodeGen::DoUnaryMathOperation(LUnaryMathOperation* instr) { |
| void LCodeGen::DoCallKeyed(LCallKeyed* instr) { |
| + ASSERT(ToRegister(instr->context()).is(esi)); |
| + ASSERT(ToRegister(instr->key()).is(ecx)); |
| ASSERT(ToRegister(instr->result()).is(eax)); |
| - ASSERT(ToRegister(instr->InputAt(0)).is(ecx)); |
| int arity = instr->arity(); |
| Handle<Code> ic = StubCache::ComputeKeyedCallInitialize(arity, NOT_IN_LOOP); |
| CallCode(ic, RelocInfo::CODE_TARGET, instr); |
| - __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); |
| } |
| void LCodeGen::DoCallNamed(LCallNamed* instr) { |
| + ASSERT(ToRegister(instr->context()).is(esi)); |
| ASSERT(ToRegister(instr->result()).is(eax)); |
| int arity = instr->arity(); |
| Handle<Code> ic = StubCache::ComputeCallInitialize(arity, NOT_IN_LOOP); |
| __ mov(ecx, instr->name()); |
| CallCode(ic, RelocInfo::CODE_TARGET, instr); |
| - __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); |
| } |
| void LCodeGen::DoCallFunction(LCallFunction* instr) { |
| + ASSERT(ToRegister(instr->context()).is(esi)); |
| ASSERT(ToRegister(instr->result()).is(eax)); |
| int arity = instr->arity(); |
| CallFunctionStub stub(arity, NOT_IN_LOOP, RECEIVER_MIGHT_BE_VALUE); |
| CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); |
| __ Drop(1); |
| - __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); |
| } |
| void LCodeGen::DoCallGlobal(LCallGlobal* instr) { |
| + ASSERT(ToRegister(instr->context()).is(esi)); |
| ASSERT(ToRegister(instr->result()).is(eax)); |
| int arity = instr->arity(); |
| Handle<Code> ic = StubCache::ComputeCallInitialize(arity, NOT_IN_LOOP); |
| __ mov(ecx, instr->name()); |
| CallCode(ic, RelocInfo::CODE_TARGET_CONTEXT, instr); |
| - __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); |
| } |
| @@ -2591,7 +2608,8 @@ void LCodeGen::DoCallKnownGlobal(LCallKnownGlobal* instr) { |
| void LCodeGen::DoCallNew(LCallNew* instr) { |
| - ASSERT(ToRegister(instr->InputAt(0)).is(edi)); |
| + ASSERT(ToRegister(instr->context()).is(esi)); |
| + ASSERT(ToRegister(instr->constructor()).is(edi)); |
| ASSERT(ToRegister(instr->result()).is(eax)); |
| Handle<Code> builtin(Builtins::builtin(Builtins::JSConstructCall)); |
| @@ -2601,7 +2619,7 @@ void LCodeGen::DoCallNew(LCallNew* instr) { |
| void LCodeGen::DoCallRuntime(LCallRuntime* instr) { |
| - CallRuntime(instr->function(), instr->arity(), instr); |
| + CallRuntime(instr->function(), instr->arity(), instr, false); |
| } |
| @@ -2636,6 +2654,7 @@ void LCodeGen::DoStoreNamedField(LStoreNamedField* instr) { |
| void LCodeGen::DoStoreNamedGeneric(LStoreNamedGeneric* instr) { |
| + ASSERT(ToRegister(instr->context()).is(esi)); |
| ASSERT(ToRegister(instr->object()).is(edx)); |
| ASSERT(ToRegister(instr->value()).is(eax)); |
| @@ -2684,6 +2703,7 @@ void LCodeGen::DoStoreKeyedFastElement(LStoreKeyedFastElement* instr) { |
| void LCodeGen::DoStoreKeyedGeneric(LStoreKeyedGeneric* instr) { |
| + ASSERT(ToRegister(instr->context()).is(esi)); |
| ASSERT(ToRegister(instr->object()).is(edx)); |
| ASSERT(ToRegister(instr->key()).is(ecx)); |
| ASSERT(ToRegister(instr->value()).is(eax)); |
| @@ -2819,6 +2839,7 @@ void LCodeGen::DoDeferredStringCharCodeAt(LStringCharCodeAt* instr) { |
| __ SmiTag(index); |
| __ push(index); |
| } |
| + __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); |
| __ CallRuntimeSaveDoubles(Runtime::kStringCharCodeAt); |
| RecordSafepointWithRegisters( |
| instr->pointer_map(), 2, Safepoint::kNoDeoptimizationIndex); |
| @@ -2896,6 +2917,7 @@ void LCodeGen::DoDeferredNumberTagI(LNumberTagI* instr) { |
| // integer value. |
| __ mov(Operand(esp, EspIndexForPushAll(reg) * kPointerSize), Immediate(0)); |
| + __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); |
| __ CallRuntimeSaveDoubles(Runtime::kAllocateHeapNumber); |
| RecordSafepointWithRegisters( |
| instr->pointer_map(), 0, Safepoint::kNoDeoptimizationIndex); |
| @@ -2943,6 +2965,7 @@ void LCodeGen::DoDeferredNumberTagD(LNumberTagD* instr) { |
| __ Set(reg, Immediate(0)); |
| __ PushSafepointRegisters(); |
| + __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); |
| __ CallRuntimeSaveDoubles(Runtime::kAllocateHeapNumber); |
| RecordSafepointWithRegisters( |
| instr->pointer_map(), 0, Safepoint::kNoDeoptimizationIndex); |
| @@ -3358,21 +3381,22 @@ void LCodeGen::DoArrayLiteral(LArrayLiteral* instr) { |
| FastCloneShallowArrayStub::Mode mode = |
| FastCloneShallowArrayStub::COPY_ON_WRITE_ELEMENTS; |
| FastCloneShallowArrayStub stub(mode, length); |
| - CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); |
| + CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr, false); |
| } else if (instr->hydrogen()->depth() > 1) { |
| - CallRuntime(Runtime::kCreateArrayLiteral, 3, instr); |
| + CallRuntime(Runtime::kCreateArrayLiteral, 3, instr, false); |
| } else if (length > FastCloneShallowArrayStub::kMaximumClonedLength) { |
| - CallRuntime(Runtime::kCreateArrayLiteralShallow, 3, instr); |
| + CallRuntime(Runtime::kCreateArrayLiteralShallow, 3, instr, false); |
| } else { |
| FastCloneShallowArrayStub::Mode mode = |
| FastCloneShallowArrayStub::CLONE_ELEMENTS; |
| FastCloneShallowArrayStub stub(mode, length); |
| - CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); |
| + CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr, false); |
| } |
| } |
| void LCodeGen::DoObjectLiteral(LObjectLiteral* instr) { |
| + ASSERT(ToRegister(instr->context()).is(esi)); |
| // Setup the parameters to the stub/runtime call. |
| __ mov(eax, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); |
| __ push(FieldOperand(eax, JSFunction::kLiteralsOffset)); |
| @@ -3410,7 +3434,7 @@ void LCodeGen::DoRegExpLiteral(LRegExpLiteral* instr) { |
| __ push(Immediate(Smi::FromInt(instr->hydrogen()->literal_index()))); |
| __ push(Immediate(instr->hydrogen()->pattern())); |
| __ push(Immediate(instr->hydrogen()->flags())); |
| - CallRuntime(Runtime::kMaterializeRegExpLiteral, 4, instr); |
| + CallRuntime(Runtime::kMaterializeRegExpLiteral, 4, instr, false); |
| __ mov(ebx, eax); |
| __ bind(&materialized); |
| @@ -3422,7 +3446,7 @@ void LCodeGen::DoRegExpLiteral(LRegExpLiteral* instr) { |
| __ bind(&runtime_allocate); |
| __ push(ebx); |
| __ push(Immediate(Smi::FromInt(size))); |
| - CallRuntime(Runtime::kAllocateInNewSpace, 1, instr); |
| + CallRuntime(Runtime::kAllocateInNewSpace, 1, instr, false); |
| __ pop(ebx); |
| __ bind(&allocated); |
| @@ -3449,14 +3473,14 @@ void LCodeGen::DoFunctionLiteral(LFunctionLiteral* instr) { |
| if (shared_info->num_literals() == 0 && !pretenure) { |
| FastNewClosureStub stub; |
| __ push(Immediate(shared_info)); |
| - CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); |
| + CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr, false); |
| } else { |
| - __ push(esi); |
| + __ push(Operand(ebp, StandardFrameConstants::kContextOffset)); |
| __ push(Immediate(shared_info)); |
| __ push(Immediate(pretenure |
| ? Factory::true_value() |
| : Factory::false_value())); |
| - CallRuntime(Runtime::kNewClosure, 3, instr); |
| + CallRuntime(Runtime::kNewClosure, 3, instr, false); |
| } |
| } |
| @@ -3468,7 +3492,7 @@ void LCodeGen::DoTypeof(LTypeof* instr) { |
| } else { |
| __ push(ToOperand(input)); |
| } |
| - CallRuntime(Runtime::kTypeof, 1, instr); |
| + CallRuntime(Runtime::kTypeof, 1, instr, false); |
| } |
| @@ -3662,6 +3686,7 @@ void LCodeGen::DoDeleteProperty(LDeleteProperty* instr) { |
| SafepointGenerator safepoint_generator(this, |
| pointers, |
| env->deoptimization_index()); |
| + __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); |
| __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION, &safepoint_generator); |
| } |
| @@ -3674,7 +3699,7 @@ void LCodeGen::DoStackCheck(LStackCheck* instr) { |
| __ j(above_equal, &done); |
| StackCheckStub stub; |
| - CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); |
| + CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr, false); |
| __ bind(&done); |
| } |