OLD | NEW |
1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 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 5106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5117 | 5117 |
5118 __ bind(&done); | 5118 __ bind(&done); |
5119 __ add(sp, sp, Operand(3 * kPointerSize)); | 5119 __ add(sp, sp, Operand(3 * kPointerSize)); |
5120 __ Ret(); | 5120 __ Ret(); |
5121 | 5121 |
5122 __ bind(&slowcase); | 5122 __ bind(&slowcase); |
5123 __ TailCallRuntime(Runtime::kRegExpConstructResult, 3, 1); | 5123 __ TailCallRuntime(Runtime::kRegExpConstructResult, 3, 1); |
5124 } | 5124 } |
5125 | 5125 |
5126 | 5126 |
5127 void CallFunctionStub::FinishCode(Handle<Code> code) { | 5127 static void GenerateRecordCallTarget(MacroAssembler* masm) { |
5128 code->set_has_function_cache(false); | 5128 // Cache the called function in a global property cell. Cache states |
5129 } | 5129 // are uninitialized, monomorphic (indicated by a JSFunction), and |
| 5130 // megamorphic. |
| 5131 // r1 : the function to call |
| 5132 // r2 : cache cell for call target |
| 5133 Isolate* isolate = masm->isolate(); |
| 5134 Label done; |
5130 | 5135 |
| 5136 ASSERT_EQ(*TypeFeedbackCells::MegamorphicSentinel(isolate), |
| 5137 isolate->heap()->undefined_value()); |
| 5138 ASSERT_EQ(*TypeFeedbackCells::UninitializedSentinel(isolate), |
| 5139 isolate->heap()->the_hole_value()); |
5131 | 5140 |
5132 void CallFunctionStub::Clear(Heap* heap, Address address) { | 5141 // Load the cache state into r3. |
5133 UNREACHABLE(); | 5142 __ ldr(r3, FieldMemOperand(r2, JSGlobalPropertyCell::kValueOffset)); |
5134 } | |
5135 | 5143 |
| 5144 // A monomorphic cache hit or an already megamorphic state: invoke the |
| 5145 // function without changing the state. |
| 5146 __ cmp(r3, r1); |
| 5147 __ b(eq, &done); |
| 5148 __ CompareRoot(r3, Heap::kUndefinedValueRootIndex); |
| 5149 __ b(eq, &done); |
5136 | 5150 |
5137 Object* CallFunctionStub::GetCachedValue(Address address) { | 5151 // A monomorphic miss (i.e, here the cache is not uninitialized) goes |
5138 UNREACHABLE(); | 5152 // megamorphic. |
5139 return NULL; | 5153 __ CompareRoot(r3, Heap::kTheHoleValueRootIndex); |
| 5154 // MegamorphicSentinel is an immortal immovable object (undefined) so no |
| 5155 // write-barrier is needed. |
| 5156 __ LoadRoot(ip, Heap::kUndefinedValueRootIndex, ne); |
| 5157 __ str(ip, FieldMemOperand(r2, JSGlobalPropertyCell::kValueOffset), ne); |
| 5158 |
| 5159 // An uninitialized cache is patched with the function. |
| 5160 __ str(r1, FieldMemOperand(r2, JSGlobalPropertyCell::kValueOffset), eq); |
| 5161 // No need for a write barrier here - cells are rescanned. |
| 5162 |
| 5163 __ bind(&done); |
5140 } | 5164 } |
5141 | 5165 |
5142 | 5166 |
5143 void CallFunctionStub::Generate(MacroAssembler* masm) { | 5167 void CallFunctionStub::Generate(MacroAssembler* masm) { |
5144 // r1 : the function to call | 5168 // r1 : the function to call |
| 5169 // r2 : cache cell for call target |
5145 Label slow, non_function; | 5170 Label slow, non_function; |
5146 | 5171 |
5147 // The receiver might implicitly be the global object. This is | 5172 // The receiver might implicitly be the global object. This is |
5148 // indicated by passing the hole as the receiver to the call | 5173 // indicated by passing the hole as the receiver to the call |
5149 // function stub. | 5174 // function stub. |
5150 if (ReceiverMightBeImplicit()) { | 5175 if (ReceiverMightBeImplicit()) { |
5151 Label call; | 5176 Label call; |
5152 // Get the receiver from the stack. | 5177 // Get the receiver from the stack. |
5153 // function, receiver [, arguments] | 5178 // function, receiver [, arguments] |
5154 __ ldr(r4, MemOperand(sp, argc_ * kPointerSize)); | 5179 __ ldr(r4, MemOperand(sp, argc_ * kPointerSize)); |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5212 __ str(r1, MemOperand(sp, argc_ * kPointerSize)); | 5237 __ str(r1, MemOperand(sp, argc_ * kPointerSize)); |
5213 __ mov(r0, Operand(argc_)); // Set up the number of arguments. | 5238 __ mov(r0, Operand(argc_)); // Set up the number of arguments. |
5214 __ mov(r2, Operand(0, RelocInfo::NONE)); | 5239 __ mov(r2, Operand(0, RelocInfo::NONE)); |
5215 __ GetBuiltinEntry(r3, Builtins::CALL_NON_FUNCTION); | 5240 __ GetBuiltinEntry(r3, Builtins::CALL_NON_FUNCTION); |
5216 __ SetCallKind(r5, CALL_AS_METHOD); | 5241 __ SetCallKind(r5, CALL_AS_METHOD); |
5217 __ Jump(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(), | 5242 __ Jump(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(), |
5218 RelocInfo::CODE_TARGET); | 5243 RelocInfo::CODE_TARGET); |
5219 } | 5244 } |
5220 | 5245 |
5221 | 5246 |
| 5247 void CallConstructStub::Generate(MacroAssembler* masm) { |
| 5248 // r0 : number of arguments |
| 5249 // r1 : the function to call |
| 5250 // r2 : cache cell for call target |
| 5251 Label slow, non_function_call; |
| 5252 |
| 5253 // Check that the function is not a smi. |
| 5254 __ JumpIfSmi(r1, &non_function_call); |
| 5255 // Check that the function is a JSFunction. |
| 5256 __ CompareObjectType(r1, r3, r3, JS_FUNCTION_TYPE); |
| 5257 __ b(ne, &slow); |
| 5258 |
| 5259 if (RecordCallTarget()) { |
| 5260 GenerateRecordCallTarget(masm); |
| 5261 } |
| 5262 |
| 5263 // Jump to the function-specific construct stub. |
| 5264 __ ldr(r2, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset)); |
| 5265 __ ldr(r2, FieldMemOperand(r2, SharedFunctionInfo::kConstructStubOffset)); |
| 5266 __ add(pc, r2, Operand(Code::kHeaderSize - kHeapObjectTag)); |
| 5267 |
| 5268 // r0: number of arguments |
| 5269 // r1: called object |
| 5270 // r3: object type |
| 5271 Label do_call; |
| 5272 __ bind(&slow); |
| 5273 __ cmp(r3, Operand(JS_FUNCTION_PROXY_TYPE)); |
| 5274 __ b(ne, &non_function_call); |
| 5275 __ GetBuiltinEntry(r3, Builtins::CALL_FUNCTION_PROXY_AS_CONSTRUCTOR); |
| 5276 __ jmp(&do_call); |
| 5277 |
| 5278 __ bind(&non_function_call); |
| 5279 __ GetBuiltinEntry(r3, Builtins::CALL_NON_FUNCTION_AS_CONSTRUCTOR); |
| 5280 __ bind(&do_call); |
| 5281 // Set expected number of arguments to zero (not changing r0). |
| 5282 __ mov(r2, Operand(0, RelocInfo::NONE)); |
| 5283 __ SetCallKind(r5, CALL_AS_METHOD); |
| 5284 __ Jump(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(), |
| 5285 RelocInfo::CODE_TARGET); |
| 5286 } |
| 5287 |
| 5288 |
5222 // Unfortunately you have to run without snapshots to see most of these | 5289 // Unfortunately you have to run without snapshots to see most of these |
5223 // names in the profile since most compare stubs end up in the snapshot. | 5290 // names in the profile since most compare stubs end up in the snapshot. |
5224 void CompareStub::PrintName(StringStream* stream) { | 5291 void CompareStub::PrintName(StringStream* stream) { |
5225 ASSERT((lhs_.is(r0) && rhs_.is(r1)) || | 5292 ASSERT((lhs_.is(r0) && rhs_.is(r1)) || |
5226 (lhs_.is(r1) && rhs_.is(r0))); | 5293 (lhs_.is(r1) && rhs_.is(r0))); |
5227 const char* cc_name; | 5294 const char* cc_name; |
5228 switch (cc_) { | 5295 switch (cc_) { |
5229 case lt: cc_name = "LT"; break; | 5296 case lt: cc_name = "LT"; break; |
5230 case gt: cc_name = "GT"; break; | 5297 case gt: cc_name = "GT"; break; |
5231 case le: cc_name = "LE"; break; | 5298 case le: cc_name = "LE"; break; |
(...skipping 2082 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7314 __ StoreNumberToDoubleElements(r0, r3, r1, r5, r6, r7, r9, r10, | 7381 __ StoreNumberToDoubleElements(r0, r3, r1, r5, r6, r7, r9, r10, |
7315 &slow_elements); | 7382 &slow_elements); |
7316 __ Ret(); | 7383 __ Ret(); |
7317 } | 7384 } |
7318 | 7385 |
7319 #undef __ | 7386 #undef __ |
7320 | 7387 |
7321 } } // namespace v8::internal | 7388 } } // namespace v8::internal |
7322 | 7389 |
7323 #endif // V8_TARGET_ARCH_ARM | 7390 #endif // V8_TARGET_ARCH_ARM |
OLD | NEW |