Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(17)

Unified Diff: src/x64/ic-x64.cc

Issue 162009: X64: Make megamorphic and normal calls use stub cache and stub code. (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: Created 11 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/x64/ic-x64.cc
===================================================================
--- src/x64/ic-x64.cc (revision 2628)
+++ src/x64/ic-x64.cc (working copy)
@@ -562,13 +562,175 @@
__ InvokeFunction(rdi, actual, JUMP_FUNCTION);
}
+
+// Defined in ic.cc.
+Object* CallIC_Miss(Arguments args);
+
void CallIC::GenerateMegamorphic(MacroAssembler* masm, int argc) {
+ // ----------- S t a t e -------------
+ // rsp[0] return address
+ // rsp[8] argument argc
+ // rsp[16] argument argc - 1
+ // ...
+ // rsp[argc * 8] argument 1
+ // rsp[(argc + 1) * 8] argument 0 = reciever
+ // rsp[(argc + 2) * 8] function name
+ // -----------------------------------
+ Label number, non_number, non_string, boolean, probe, miss;
+
+ // Get the receiver of the function from the stack; 1 ~ return address.
+ __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize));
+ // Get the name of the function from the stack; 2 ~ return address, receiver
+ __ movq(rcx, Operand(rsp, (argc + 2) * kPointerSize));
+
+ // Probe the stub cache.
+ Code::Flags flags =
+ Code::ComputeFlags(Code::CALL_IC, NOT_IN_LOOP, MONOMORPHIC, NORMAL, argc);
+ StubCache::GenerateProbe(masm, flags, rdx, rcx, rbx, rax);
+
+ // If the stub cache probing failed, the receiver might be a value.
+ // For value objects, we use the map of the prototype objects for
+ // the corresponding JSValue for the cache and that is what we need
+ // to probe.
+ //
+ // Check for number.
+ __ testl(rdx, Immediate(kSmiTagMask));
+ __ j(zero, &number);
+ __ CmpObjectType(rdx, HEAP_NUMBER_TYPE, rbx);
+ __ j(not_equal, &non_number);
+ __ bind(&number);
+ StubCompiler::GenerateLoadGlobalFunctionPrototype(
+ masm, Context::NUMBER_FUNCTION_INDEX, rdx);
+ __ jmp(&probe);
+
+ // Check for string.
+ __ bind(&non_number);
+ __ CmpInstanceType(rbx, FIRST_NONSTRING_TYPE);
+ __ j(above_equal, &non_string);
+ StubCompiler::GenerateLoadGlobalFunctionPrototype(
+ masm, Context::STRING_FUNCTION_INDEX, rdx);
+ __ jmp(&probe);
+
+ // Check for boolean.
+ __ bind(&non_string);
+ __ Cmp(rdx, Factory::true_value());
+ __ j(equal, &boolean);
+ __ Cmp(rdx, Factory::false_value());
+ __ j(not_equal, &miss);
+ __ bind(&boolean);
+ StubCompiler::GenerateLoadGlobalFunctionPrototype(
+ masm, Context::BOOLEAN_FUNCTION_INDEX, rdx);
+
+ // Probe the stub cache for the value object.
+ __ bind(&probe);
+ StubCache::GenerateProbe(masm, flags, rdx, rcx, rbx, no_reg);
+
// Cache miss: Jump to runtime.
+ __ bind(&miss);
Generate(masm, argc, ExternalReference(IC_Utility(kCallIC_Miss)));
}
+
+static void GenerateNormalHelper(MacroAssembler* masm,
+ int argc,
+ bool is_global_object,
+ Label* miss) {
+ // Search dictionary - put result in register edx.
+ GenerateDictionaryLoad(masm, miss, rax, rdx, rbx, rcx);
+
+ // Move the result to register rdi and check that it isn't a smi.
+ __ movq(rdi, rdx);
+ __ testl(rdx, Immediate(kSmiTagMask));
+ __ j(zero, miss);
+
+ // Check that the value is a JavaScript function.
+ __ CmpObjectType(rdx, JS_FUNCTION_TYPE, rdx);
+ __ j(not_equal, miss);
+ // Check that the function has been loaded.
+ __ testb(FieldOperand(rdx, Map::kBitField2Offset),
+ Immediate(1 << Map::kNeedsLoading));
+ __ j(not_zero, miss);
+
+ // Patch the receiver with the global proxy if necessary.
+ if (is_global_object) {
+ __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize));
+ __ movq(rdx, FieldOperand(rdx, GlobalObject::kGlobalReceiverOffset));
+ __ movq(Operand(rsp, (argc + 1) * kPointerSize), rdx);
+ }
+
+ // Invoke the function.
+ ParameterCount actual(argc);
+ __ InvokeFunction(rdi, actual, JUMP_FUNCTION);
+}
+
+
void CallIC::GenerateNormal(MacroAssembler* masm, int argc) {
+ // ----------- S t a t e -------------
+ // rsp[0] return address
+ // rsp[8] argument argc
+ // rsp[16] argument argc - 1
+ // ...
+ // rsp[argc * 8] argument 1
+ // rsp[(argc + 1) * 8] argument 0 = reciever
+ // rsp[(argc + 2) * 8] function name
+ // -----------------------------------
+
+ Label miss, global_object, non_global_object;
+
+ // Get the receiver of the function from the stack.
+ __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize));
+ // Get the name of the function from the stack.
+ __ movq(rcx, Operand(rsp, (argc + 2) * kPointerSize));
+
+ // Check that the receiver isn't a smi.
+ __ testl(rdx, Immediate(kSmiTagMask));
+ __ j(zero, &miss);
+
+ // Check that the receiver is a valid JS object.
+ // Because there are so many map checks and type checks, do not
+ // use CmpObjectType, but load map and type into registers.
+ __ movq(rbx, FieldOperand(rdx, HeapObject::kMapOffset));
+ __ movb(rax, FieldOperand(rbx, Map::kInstanceTypeOffset));
+ __ cmpb(rax, Immediate(FIRST_JS_OBJECT_TYPE));
+ __ j(below, &miss);
+
+ // If this assert fails, we have to check upper bound too.
+ ASSERT(LAST_TYPE == JS_FUNCTION_TYPE);
+
+ // Check for access to global object.
+ __ cmpb(rax, Immediate(JS_GLOBAL_OBJECT_TYPE));
+ __ j(equal, &global_object);
+ __ cmpb(rax, Immediate(JS_BUILTINS_OBJECT_TYPE));
+ __ j(not_equal, &non_global_object);
+
+ // Accessing global object: Load and invoke.
+ __ bind(&global_object);
+ // Check that the global object does not require access checks.
+ __ movb(rbx, FieldOperand(rbx, Map::kBitFieldOffset));
+ __ testb(rbx, Immediate(1 << Map::kIsAccessCheckNeeded));
+ __ j(not_equal, &miss);
+ GenerateNormalHelper(masm, argc, true, &miss);
+
+ // Accessing non-global object: Check for access to global proxy.
+ Label global_proxy, invoke;
+ __ bind(&non_global_object);
+ __ cmpb(rax, Immediate(JS_GLOBAL_PROXY_TYPE));
+ __ j(equal, &global_proxy);
+ // Check that the non-global, non-global-proxy object does not
+ // require access checks.
+ __ movb(rbx, FieldOperand(rbx, Map::kBitFieldOffset));
+ __ testb(rbx, Immediate(1 << Map::kIsAccessCheckNeeded));
+ __ j(not_equal, &miss);
+ __ bind(&invoke);
+ GenerateNormalHelper(masm, argc, false, &miss);
+
+ // Global object proxy access: Check access rights.
+ __ bind(&global_proxy);
+ __ CheckAccessGlobalProxy(rdx, rax, &miss);
+ __ jmp(&invoke);
+
// Cache miss: Jump to runtime.
+ __ bind(&miss);
Generate(masm, argc, ExternalReference(IC_Utility(kCallIC_Miss)));
}
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698