Index: src/x64/stub-cache-x64.cc |
diff --git a/src/x64/stub-cache-x64.cc b/src/x64/stub-cache-x64.cc |
index e0644cd63b0578ae303d356123cf6149a65fe141..e4ab2325ad054dc8a7f7ff594b6feb90559f7da0 100644 |
--- a/src/x64/stub-cache-x64.cc |
+++ b/src/x64/stub-cache-x64.cc |
@@ -1291,8 +1291,69 @@ Object* CallStubCompiler::CompileStringCharAtCall(Object* object, |
JSFunction* function, |
String* name, |
CheckType check) { |
- // TODO(722): implement this. |
- return Heap::undefined_value(); |
+ // ----------- S t a t e ------------- |
+ // -- rcx : function name |
+ // -- rsp[0] : return address |
+ // -- rsp[(argc - n) * 8] : arg[n] (zero-based) |
+ // -- ... |
+ // -- rsp[(argc + 1) * 8] : receiver |
+ // ----------------------------------- |
+ |
+ // If object is not a string, bail out to regular call. |
+ if (!object->IsString()) return Heap::undefined_value(); |
+ |
+ const int argc = arguments().immediate(); |
+ |
+ Label miss; |
+ Label index_out_of_range; |
+ |
+ GenerateNameCheck(name, &miss); |
+ |
+ // Check that the maps starting from the prototype haven't changed. |
+ GenerateDirectLoadGlobalFunctionPrototype(masm(), |
+ Context::STRING_FUNCTION_INDEX, |
+ rax); |
+ ASSERT(object != holder); |
+ CheckPrototypes(JSObject::cast(object->GetPrototype()), rax, holder, |
+ rbx, rdx, rdi, name, &miss); |
+ |
+ Register receiver = rax; |
+ Register index = rdi; |
+ Register scratch1 = rbx; |
+ Register scratch2 = rdx; |
+ Register result = rax; |
+ __ movq(receiver, Operand(rsp, (argc + 1) * kPointerSize)); |
+ if (argc > 0) { |
+ __ movq(index, Operand(rsp, (argc - 0) * kPointerSize)); |
+ } else { |
+ __ LoadRoot(index, Heap::kUndefinedValueRootIndex); |
+ } |
+ |
+ StringCharAtGenerator char_at_generator(receiver, |
+ index, |
+ scratch1, |
+ scratch2, |
+ result, |
+ &miss, // When not a string. |
+ &miss, // When not a number. |
+ &index_out_of_range, |
+ STRING_INDEX_IS_NUMBER); |
+ char_at_generator.GenerateFast(masm()); |
+ __ ret((argc + 1) * kPointerSize); |
+ |
+ ICRuntimeCallHelper call_helper; |
+ char_at_generator.GenerateSlow(masm(), call_helper); |
+ |
+ __ bind(&index_out_of_range); |
+ __ LoadRoot(rax, Heap::kEmptyStringRootIndex); |
+ __ ret((argc + 1) * kPointerSize); |
+ |
+ __ bind(&miss); |
+ Object* obj = GenerateMissBranch(); |
+ if (obj->IsFailure()) return obj; |
+ |
+ // Return the generated code. |
+ return GetCode(function); |
} |
@@ -1301,10 +1362,67 @@ Object* CallStubCompiler::CompileStringCharCodeAtCall(Object* object, |
JSFunction* function, |
String* name, |
CheckType check) { |
- // TODO(722): implement this. |
- return Heap::undefined_value(); |
-} |
+ // ----------- S t a t e ------------- |
+ // -- rcx : function name |
+ // -- rsp[0] : return address |
+ // -- rsp[(argc - n) * 8] : arg[n] (zero-based) |
+ // -- ... |
+ // -- rsp[(argc + 1) * 8] : receiver |
+ // ----------------------------------- |
+ |
+ // If object is not a string, bail out to regular call. |
+ if (!object->IsString()) return Heap::undefined_value(); |
+ |
+ const int argc = arguments().immediate(); |
+ |
+ Label miss; |
+ Label index_out_of_range; |
+ GenerateNameCheck(name, &miss); |
+ |
+ // Check that the maps starting from the prototype haven't changed. |
+ GenerateDirectLoadGlobalFunctionPrototype(masm(), |
+ Context::STRING_FUNCTION_INDEX, |
+ rax); |
+ ASSERT(object != holder); |
+ CheckPrototypes(JSObject::cast(object->GetPrototype()), rax, holder, |
+ rbx, rdx, rdi, name, &miss); |
+ |
+ Register receiver = rbx; |
+ Register index = rdi; |
+ Register scratch = rdx; |
+ Register result = rax; |
+ __ movq(receiver, Operand(rsp, (argc + 1) * kPointerSize)); |
+ if (argc > 0) { |
+ __ movq(index, Operand(rsp, (argc - 0) * kPointerSize)); |
+ } else { |
+ __ LoadRoot(index, Heap::kUndefinedValueRootIndex); |
+ } |
+ |
+ StringCharCodeAtGenerator char_code_at_generator(receiver, |
+ index, |
+ scratch, |
+ result, |
+ &miss, // When not a string. |
+ &miss, // When not a number. |
+ &index_out_of_range, |
+ STRING_INDEX_IS_NUMBER); |
+ char_code_at_generator.GenerateFast(masm()); |
+ __ ret((argc + 1) * kPointerSize); |
+ |
+ ICRuntimeCallHelper call_helper; |
+ char_code_at_generator.GenerateSlow(masm(), call_helper); |
+ |
+ __ bind(&index_out_of_range); |
+ __ LoadRoot(rax, Heap::kNanValueRootIndex); |
+ __ ret((argc + 1) * kPointerSize); |
+ __ bind(&miss); |
+ Object* obj = GenerateMissBranch(); |
+ if (obj->IsFailure()) return obj; |
+ |
+ // Return the generated code. |
+ return GetCode(function); |
+} |
Object* CallStubCompiler::CompileCallInterceptor(JSObject* object, |