Index: src/x64/full-codegen-x64.cc |
diff --git a/src/x64/full-codegen-x64.cc b/src/x64/full-codegen-x64.cc |
index 577c92cd62802713d09cbbc28e18b800f80d382d..25f9c1d7a4df6a1f469c850939901739b163c72b 100644 |
--- a/src/x64/full-codegen-x64.cc |
+++ b/src/x64/full-codegen-x64.cc |
@@ -1904,76 +1904,6 @@ void FullCodeGenerator::VisitCallNew(CallNew* expr) { |
} |
-void FullCodeGenerator::EmitInlineRuntimeCall(CallRuntime* expr) { |
- Handle<String> name = expr->name(); |
- if (strcmp("_IsSmi", *name->ToCString()) == 0) { |
- EmitIsSmi(expr->arguments()); |
- } else if (strcmp("_IsNonNegativeSmi", *name->ToCString()) == 0) { |
- EmitIsNonNegativeSmi(expr->arguments()); |
- } else if (strcmp("_IsObject", *name->ToCString()) == 0) { |
- EmitIsObject(expr->arguments()); |
- } else if (strcmp("_IsUndetectableObject", *name->ToCString()) == 0) { |
- EmitIsUndetectableObject(expr->arguments()); |
- } else if (strcmp("_IsFunction", *name->ToCString()) == 0) { |
- EmitIsFunction(expr->arguments()); |
- } else if (strcmp("_IsArray", *name->ToCString()) == 0) { |
- EmitIsArray(expr->arguments()); |
- } else if (strcmp("_IsRegExp", *name->ToCString()) == 0) { |
- EmitIsRegExp(expr->arguments()); |
- } else if (strcmp("_IsConstructCall", *name->ToCString()) == 0) { |
- EmitIsConstructCall(expr->arguments()); |
- } else if (strcmp("_ObjectEquals", *name->ToCString()) == 0) { |
- EmitObjectEquals(expr->arguments()); |
- } else if (strcmp("_Arguments", *name->ToCString()) == 0) { |
- EmitArguments(expr->arguments()); |
- } else if (strcmp("_ArgumentsLength", *name->ToCString()) == 0) { |
- EmitArgumentsLength(expr->arguments()); |
- } else if (strcmp("_ClassOf", *name->ToCString()) == 0) { |
- EmitClassOf(expr->arguments()); |
- } else if (strcmp("_Log", *name->ToCString()) == 0) { |
- EmitLog(expr->arguments()); |
- } else if (strcmp("_RandomHeapNumber", *name->ToCString()) == 0) { |
- EmitRandomHeapNumber(expr->arguments()); |
- } else if (strcmp("_SubString", *name->ToCString()) == 0) { |
- EmitSubString(expr->arguments()); |
- } else if (strcmp("_RegExpExec", *name->ToCString()) == 0) { |
- EmitRegExpExec(expr->arguments()); |
- } else if (strcmp("_ValueOf", *name->ToCString()) == 0) { |
- EmitValueOf(expr->arguments()); |
- } else if (strcmp("_SetValueOf", *name->ToCString()) == 0) { |
- EmitSetValueOf(expr->arguments()); |
- } else if (strcmp("_NumberToString", *name->ToCString()) == 0) { |
- EmitNumberToString(expr->arguments()); |
- } else if (strcmp("_CharFromCode", *name->ToCString()) == 0) { |
- EmitCharFromCode(expr->arguments()); |
- } else if (strcmp("_FastCharCodeAt", *name->ToCString()) == 0) { |
- EmitFastCharCodeAt(expr->arguments()); |
- } else if (strcmp("_StringAdd", *name->ToCString()) == 0) { |
- EmitStringAdd(expr->arguments()); |
- } else if (strcmp("_StringCompare", *name->ToCString()) == 0) { |
- EmitStringCompare(expr->arguments()); |
- } else if (strcmp("_MathPow", *name->ToCString()) == 0) { |
- EmitMathPow(expr->arguments()); |
- } else if (strcmp("_MathSin", *name->ToCString()) == 0) { |
- EmitMathSin(expr->arguments()); |
- } else if (strcmp("_MathCos", *name->ToCString()) == 0) { |
- EmitMathCos(expr->arguments()); |
- } else if (strcmp("_MathSqrt", *name->ToCString()) == 0) { |
- EmitMathSqrt(expr->arguments()); |
- } else if (strcmp("_CallFunction", *name->ToCString()) == 0) { |
- EmitCallFunction(expr->arguments()); |
- } else if (strcmp("_RegExpConstructResult", *name->ToCString()) == 0) { |
- EmitRegExpConstructResult(expr->arguments()); |
- } else if (strcmp("_SwapElements", *name->ToCString()) == 0) { |
- EmitSwapElements(expr->arguments()); |
- } else if (strcmp("_GetFromCache", *name->ToCString()) == 0) { |
- EmitGetFromCache(expr->arguments()); |
- } else { |
- UNREACHABLE(); |
- } |
-} |
- |
- |
void FullCodeGenerator::EmitIsSmi(ZoneList<Expression*>* args) { |
ASSERT(args->length() == 1); |
@@ -2412,46 +2342,120 @@ void FullCodeGenerator::EmitNumberToString(ZoneList<Expression*>* args) { |
} |
-void FullCodeGenerator::EmitCharFromCode(ZoneList<Expression*>* args) { |
+void FullCodeGenerator::EmitStringCharFromCode(ZoneList<Expression*>* args) { |
ASSERT(args->length() == 1); |
VisitForValue(args->at(0), kAccumulator); |
- Label slow_case, done; |
- // Fast case of Heap::LookupSingleCharacterStringFromCode. |
- __ JumpIfNotSmi(rax, &slow_case); |
- __ SmiToInteger32(rcx, rax); |
- __ cmpl(rcx, Immediate(String::kMaxAsciiCharCode)); |
- __ j(above, &slow_case); |
+ Label done; |
+ StringCharFromCodeGenerator generator(rax, rbx); |
+ generator.GenerateFast(masm_); |
+ __ jmp(&done); |
- __ Move(rbx, Factory::single_character_string_cache()); |
- __ movq(rbx, FieldOperand(rbx, |
- rcx, |
- times_pointer_size, |
- FixedArray::kHeaderSize)); |
+ NopRuntimeCallHelper call_helper; |
+ generator.GenerateSlow(masm_, call_helper); |
- __ CompareRoot(rbx, Heap::kUndefinedValueRootIndex); |
- __ j(equal, &slow_case); |
- __ movq(rax, rbx); |
+ __ bind(&done); |
+ Apply(context_, rbx); |
+} |
+ |
+ |
+void FullCodeGenerator::EmitStringCharCodeAt(ZoneList<Expression*>* args) { |
+ ASSERT(args->length() == 2); |
+ |
+ VisitForValue(args->at(0), kStack); |
+ VisitForValue(args->at(1), kAccumulator); |
+ |
+ Register object = rbx; |
+ Register index = rax; |
+ Register scratch = rcx; |
+ Register result = rdx; |
+ |
+ __ pop(object); |
+ |
+ Label need_conversion; |
+ Label index_out_of_range; |
+ Label done; |
+ StringCharCodeAtGenerator generator(object, |
+ index, |
+ scratch, |
+ result, |
+ &need_conversion, |
+ &need_conversion, |
+ &index_out_of_range, |
+ STRING_ANY_NUMBER_INDEX); |
+ generator.GenerateFast(masm_); |
__ jmp(&done); |
- __ bind(&slow_case); |
- __ push(rax); |
- __ CallRuntime(Runtime::kCharFromCode, 1); |
+ __ bind(&index_out_of_range); |
+ // When the index is out of range, the spec requires us to return |
+ // NaN. |
+ __ LoadRoot(result, Heap::kNanValueRootIndex); |
+ __ jmp(&done); |
+ |
+ __ bind(&need_conversion); |
+ // Move the undefined value into the result register, which will |
+ // trigger conversion. |
+ __ LoadRoot(result, Heap::kUndefinedValueRootIndex); |
+ __ jmp(&done); |
+ |
+ NopRuntimeCallHelper call_helper; |
+ generator.GenerateSlow(masm_, call_helper); |
__ bind(&done); |
- Apply(context_, rax); |
+ Apply(context_, result); |
} |
-void FullCodeGenerator::EmitFastCharCodeAt(ZoneList<Expression*>* args) { |
- // TODO(fsc): Port the complete implementation from the classic back-end. |
- // Move the undefined value into the result register, which will |
- // trigger the slow case. |
- __ LoadRoot(rax, Heap::kUndefinedValueRootIndex); |
- Apply(context_, rax); |
+void FullCodeGenerator::EmitStringCharAt(ZoneList<Expression*>* args) { |
+ ASSERT(args->length() == 2); |
+ |
+ VisitForValue(args->at(0), kStack); |
+ VisitForValue(args->at(1), kAccumulator); |
+ |
+ Register object = rbx; |
+ Register index = rax; |
+ Register scratch1 = rcx; |
+ Register scratch2 = rdx; |
+ Register result = rax; |
+ |
+ __ pop(object); |
+ |
+ Label need_conversion; |
+ Label index_out_of_range; |
+ Label done; |
+ StringCharAtGenerator generator(object, |
+ index, |
+ scratch1, |
+ scratch2, |
+ result, |
+ &need_conversion, |
+ &need_conversion, |
+ &index_out_of_range, |
+ STRING_ANY_NUMBER_INDEX); |
+ generator.GenerateFast(masm_); |
+ __ jmp(&done); |
+ |
+ __ bind(&index_out_of_range); |
+ // When the index is out of range, the spec requires us to return |
+ // the empty string. |
+ __ LoadRoot(result, Heap::kEmptyStringRootIndex); |
+ __ jmp(&done); |
+ |
+ __ bind(&need_conversion); |
+ // Move smi zero into the result register, which will trigger |
+ // conversion. |
+ __ Move(result, Smi::FromInt(0)); |
+ __ jmp(&done); |
+ |
+ NopRuntimeCallHelper call_helper; |
+ generator.GenerateSlow(masm_, call_helper); |
+ |
+ __ bind(&done); |
+ Apply(context_, result); |
} |
+ |
void FullCodeGenerator::EmitStringAdd(ZoneList<Expression*>* args) { |
ASSERT_EQ(2, args->length()); |