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

Side by Side Diff: src/ia32/code-stubs-ia32.cc

Issue 5828004: IA32: Optimize instanceof... (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: '' Created 10 years 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 unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright 2010 the V8 project authors. All rights reserved. 1 // Copyright 2010 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 5022 matching lines...) Expand 10 before | Expand all | Expand 10 after
5033 __ pop(edi); 5033 __ pop(edi);
5034 __ add(Operand(esp), Immediate(2 * kPointerSize)); // remove markers 5034 __ add(Operand(esp), Immediate(2 * kPointerSize)); // remove markers
5035 5035
5036 // Restore frame pointer and return. 5036 // Restore frame pointer and return.
5037 __ pop(ebp); 5037 __ pop(ebp);
5038 __ ret(0); 5038 __ ret(0);
5039 } 5039 }
5040 5040
5041 5041
5042 void InstanceofStub::Generate(MacroAssembler* masm) { 5042 void InstanceofStub::Generate(MacroAssembler* masm) {
5043 // Get the object - go slow case if it's a smi. 5043 // Fixed register usage throughout the stub.
5044 Label slow; 5044 Register object = eax; // Object (lhs).
5045 __ mov(eax, Operand(esp, 2 * kPointerSize)); // 2 ~ return address, function 5045 Register map = ebx; // Map of the object.
5046 __ test(eax, Immediate(kSmiTagMask)); 5046 Register function = edx; // Function (rhs).
5047 __ j(zero, &slow, not_taken); 5047 Register prototype = edi; // Prototype of the function.
5048 Register scratch = ecx;
5049
5050 // Get the object and function - they are always both needed.
5051 Label slow, not_js_object;
5052 if (!args_in_registers()) {
5053 __ mov(object, Operand(esp, 2 * kPointerSize));
5054 __ mov(function, Operand(esp, 1 * kPointerSize));
5055 }
5048 5056
5049 // Check that the left hand is a JS object. 5057 // Check that the left hand is a JS object.
5050 __ IsObjectJSObjectType(eax, eax, edx, &slow); 5058 __ test(object, Immediate(kSmiTagMask));
5051 5059 __ j(zero, &not_js_object, not_taken);
5052 // Get the prototype of the function. 5060 __ IsObjectJSObjectType(object, map, scratch, &not_js_object);
5053 __ mov(edx, Operand(esp, 1 * kPointerSize)); // 1 ~ return address
5054 // edx is function, eax is map.
5055 5061
5056 // Look up the function and the map in the instanceof cache. 5062 // Look up the function and the map in the instanceof cache.
5057 NearLabel miss; 5063 NearLabel miss;
5058 ExternalReference roots_address = ExternalReference::roots_address(); 5064 ExternalReference roots_address = ExternalReference::roots_address();
5059 __ mov(ecx, Immediate(Heap::kInstanceofCacheFunctionRootIndex)); 5065 __ mov(scratch, Immediate(Heap::kInstanceofCacheFunctionRootIndex));
5060 __ cmp(edx, Operand::StaticArray(ecx, times_pointer_size, roots_address)); 5066 __ cmp(function,
5067 Operand::StaticArray(scratch, times_pointer_size, roots_address));
5061 __ j(not_equal, &miss); 5068 __ j(not_equal, &miss);
5062 __ mov(ecx, Immediate(Heap::kInstanceofCacheMapRootIndex)); 5069 __ mov(scratch, Immediate(Heap::kInstanceofCacheMapRootIndex));
5063 __ cmp(eax, Operand::StaticArray(ecx, times_pointer_size, roots_address)); 5070 __ cmp(map, Operand::StaticArray(scratch, times_pointer_size, roots_address));
5064 __ j(not_equal, &miss); 5071 __ j(not_equal, &miss);
5065 __ mov(ecx, Immediate(Heap::kInstanceofCacheAnswerRootIndex)); 5072 __ mov(scratch, Immediate(Heap::kInstanceofCacheAnswerRootIndex));
5066 __ mov(eax, Operand::StaticArray(ecx, times_pointer_size, roots_address)); 5073 __ mov(eax, Operand::StaticArray(scratch, times_pointer_size, roots_address));
5067 __ ret(2 * kPointerSize); 5074 __ IncrementCounter(&Counters::instance_of_cache, 1);
5075 __ ret((args_in_registers() ? 0 : 2) * kPointerSize);
5068 5076
5069 __ bind(&miss); 5077 __ bind(&miss);
5070 __ TryGetFunctionPrototype(edx, ebx, ecx, &slow); 5078 // Get the prototype of the function.
5079 __ TryGetFunctionPrototype(function, prototype, scratch, &slow);
5071 5080
5072 // Check that the function prototype is a JS object. 5081 // Check that the function prototype is a JS object.
5073 __ test(ebx, Immediate(kSmiTagMask)); 5082 __ test(prototype, Immediate(kSmiTagMask));
5074 __ j(zero, &slow, not_taken); 5083 __ j(zero, &slow, not_taken);
5075 __ IsObjectJSObjectType(ebx, ecx, ecx, &slow); 5084 __ IsObjectJSObjectType(prototype, scratch, scratch, &slow);
5076 5085
5077 // Register mapping: 5086 // Update the golbal instanceof cache with the current map and function. The
5078 // eax is object map. 5087 // cached answer will be set when it is known.
5079 // edx is function. 5088 __ mov(scratch, Immediate(Heap::kInstanceofCacheMapRootIndex));
5080 // ebx is function prototype. 5089 __ mov(Operand::StaticArray(scratch, times_pointer_size, roots_address), map);
5081 __ mov(ecx, Immediate(Heap::kInstanceofCacheMapRootIndex)); 5090 __ mov(scratch, Immediate(Heap::kInstanceofCacheFunctionRootIndex));
5082 __ mov(Operand::StaticArray(ecx, times_pointer_size, roots_address), eax); 5091 __ mov(Operand::StaticArray(scratch, times_pointer_size, roots_address),
5083 __ mov(ecx, Immediate(Heap::kInstanceofCacheFunctionRootIndex)); 5092 function);
5084 __ mov(Operand::StaticArray(ecx, times_pointer_size, roots_address), edx);
5085 5093
5086 __ mov(ecx, FieldOperand(eax, Map::kPrototypeOffset)); 5094 // Loop through the prototype chain of the object looking for the function
5087 5095 // prototype.
5088 // Loop through the prototype chain looking for the function prototype. 5096 __ mov(scratch, FieldOperand(map, Map::kPrototypeOffset));
5089 NearLabel loop, is_instance, is_not_instance; 5097 NearLabel loop, is_instance, is_not_instance;
5090 __ bind(&loop); 5098 __ bind(&loop);
5091 __ cmp(ecx, Operand(ebx)); 5099 __ cmp(scratch, Operand(prototype));
5092 __ j(equal, &is_instance); 5100 __ j(equal, &is_instance);
5093 __ cmp(Operand(ecx), Immediate(Factory::null_value())); 5101 __ cmp(Operand(scratch), Immediate(Factory::null_value()));
5094 __ j(equal, &is_not_instance); 5102 __ j(equal, &is_not_instance);
5095 __ mov(ecx, FieldOperand(ecx, HeapObject::kMapOffset)); 5103 __ mov(scratch, FieldOperand(scratch, HeapObject::kMapOffset));
5096 __ mov(ecx, FieldOperand(ecx, Map::kPrototypeOffset)); 5104 __ mov(scratch, FieldOperand(scratch, Map::kPrototypeOffset));
5097 __ jmp(&loop); 5105 __ jmp(&loop);
5098 5106
5099 __ bind(&is_instance); 5107 __ bind(&is_instance);
5108 __ IncrementCounter(&Counters::instance_of_stub_true, 1);
5100 __ Set(eax, Immediate(0)); 5109 __ Set(eax, Immediate(0));
5101 __ mov(ecx, Immediate(Heap::kInstanceofCacheAnswerRootIndex)); 5110 __ mov(scratch, Immediate(Heap::kInstanceofCacheAnswerRootIndex));
5102 __ mov(Operand::StaticArray(ecx, times_pointer_size, roots_address), eax); 5111 __ mov(Operand::StaticArray(scratch, times_pointer_size, roots_address), eax);
5103 __ ret(2 * kPointerSize); 5112 __ ret((args_in_registers() ? 0 : 2) * kPointerSize);
5104 5113
5105 __ bind(&is_not_instance); 5114 __ bind(&is_not_instance);
5115 __ IncrementCounter(&Counters::instance_of_stub_false, 1);
5106 __ Set(eax, Immediate(Smi::FromInt(1))); 5116 __ Set(eax, Immediate(Smi::FromInt(1)));
5107 __ mov(ecx, Immediate(Heap::kInstanceofCacheAnswerRootIndex)); 5117 __ mov(scratch, Immediate(Heap::kInstanceofCacheAnswerRootIndex));
5108 __ mov(Operand::StaticArray(ecx, times_pointer_size, roots_address), eax); 5118 __ mov(Operand::StaticArray(scratch, times_pointer_size, roots_address), eax);
5109 __ ret(2 * kPointerSize); 5119 __ ret((args_in_registers() ? 0 : 2) * kPointerSize);
5120
5121 Label object_not_null, object_not_null_or_smi;
5122 __ bind(&not_js_object);
5123 // Before null, smi and string value checks, check that the rhs is a function
5124 // as for a non-function rhs an exception needs to be thrown.
5125 __ test(function, Immediate(kSmiTagMask));
5126 __ j(zero, &slow, not_taken);
5127 __ CmpObjectType(function, JS_FUNCTION_TYPE, scratch);
5128 __ j(not_equal, &slow, not_taken);
5129
5130 // Null is not instance of anything.
5131 __ cmp(object, Factory::null_value());
5132 __ j(not_equal, &object_not_null);
5133 __ IncrementCounter(&Counters::instance_of_stub_false_null, 1);
5134 __ Set(eax, Immediate(Smi::FromInt(1)));
5135 __ ret((args_in_registers() ? 0 : 2) * kPointerSize);
5136
5137 __ bind(&object_not_null);
5138 // Smi values is not instance of anything.
5139 __ test(object, Immediate(kSmiTagMask));
5140 __ j(not_zero, &object_not_null_or_smi, not_taken);
5141 __ Set(eax, Immediate(Smi::FromInt(1)));
5142 __ ret((args_in_registers() ? 0 : 2) * kPointerSize);
5143
5144 __ bind(&object_not_null_or_smi);
5145 // String values is not instance of anything.
5146 Condition is_string = masm->IsObjectStringType(object, scratch, scratch);
5147 __ j(NegateCondition(is_string), &slow);
5148 __ IncrementCounter(&Counters::instance_of_stub_false_string, 1);
5149 __ Set(eax, Immediate(Smi::FromInt(1)));
5150 __ ret((args_in_registers() ? 0 : 2) * kPointerSize);
5110 5151
5111 // Slow-case: Go through the JavaScript implementation. 5152 // Slow-case: Go through the JavaScript implementation.
5112 __ bind(&slow); 5153 __ bind(&slow);
5154 if (args_in_registers()) {
5155 // Push arguments below return address.
5156 __ pop(scratch);
5157 __ push(object);
5158 __ push(function);
5159 __ push(scratch);
5160 }
5161 __ IncrementCounter(&Counters::instance_of_slow, 1);
5113 __ InvokeBuiltin(Builtins::INSTANCE_OF, JUMP_FUNCTION); 5162 __ InvokeBuiltin(Builtins::INSTANCE_OF, JUMP_FUNCTION);
5114 } 5163 }
5115 5164
5116 5165
5117 int CompareStub::MinorKey() { 5166 int CompareStub::MinorKey() {
5118 // Encode the three parameters in a unique 16 bit value. To avoid duplicate 5167 // Encode the three parameters in a unique 16 bit value. To avoid duplicate
5119 // stubs the never NaN NaN condition is only taken into account if the 5168 // stubs the never NaN NaN condition is only taken into account if the
5120 // condition is equals. 5169 // condition is equals.
5121 ASSERT(static_cast<unsigned>(cc_) < (1 << 12)); 5170 ASSERT(static_cast<unsigned>(cc_) < (1 << 12));
5122 ASSERT(lhs_.is(no_reg) && rhs_.is(no_reg)); 5171 ASSERT(lhs_.is(no_reg) && rhs_.is(no_reg));
(...skipping 1299 matching lines...) Expand 10 before | Expand all | Expand 10 after
6422 // Do a tail call to the rewritten stub. 6471 // Do a tail call to the rewritten stub.
6423 __ jmp(Operand(edi)); 6472 __ jmp(Operand(edi));
6424 } 6473 }
6425 6474
6426 6475
6427 #undef __ 6476 #undef __
6428 6477
6429 } } // namespace v8::internal 6478 } } // namespace v8::internal
6430 6479
6431 #endif // V8_TARGET_ARCH_IA32 6480 #endif // V8_TARGET_ARCH_IA32
OLDNEW
« no previous file with comments | « src/code-stubs.h ('k') | src/ia32/codegen-ia32.cc » ('j') | src/v8-counters.h » ('J')

Powered by Google App Engine
This is Rietveld 408576698