OLD | NEW |
1 // Copyright 2014 the V8 project authors. All rights reserved. | 1 // Copyright 2014 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/v8.h" | 5 #include "src/v8.h" |
6 | 6 |
7 #if V8_TARGET_ARCH_ARM | 7 #if V8_TARGET_ARCH_PPC |
8 | 8 |
9 #include "src/ic/call-optimization.h" | 9 #include "src/ic/call-optimization.h" |
10 #include "src/ic/handler-compiler.h" | 10 #include "src/ic/handler-compiler.h" |
11 #include "src/ic/ic.h" | 11 #include "src/ic/ic.h" |
12 | 12 |
13 namespace v8 { | 13 namespace v8 { |
14 namespace internal { | 14 namespace internal { |
15 | 15 |
16 #define __ ACCESS_MASM(masm) | 16 #define __ ACCESS_MASM(masm) |
17 | 17 |
18 | 18 |
19 void NamedLoadHandlerCompiler::GenerateLoadViaGetter( | 19 void NamedLoadHandlerCompiler::GenerateLoadViaGetter( |
20 MacroAssembler* masm, Handle<HeapType> type, Register receiver, | 20 MacroAssembler* masm, Handle<HeapType> type, Register receiver, |
21 Handle<JSFunction> getter) { | 21 Handle<JSFunction> getter) { |
22 // ----------- S t a t e ------------- | 22 // ----------- S t a t e ------------- |
23 // -- r0 : receiver | 23 // -- r3 : receiver |
24 // -- r2 : name | 24 // -- r5 : name |
25 // -- lr : return address | 25 // -- lr : return address |
26 // ----------------------------------- | 26 // ----------------------------------- |
27 { | 27 { |
28 FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL); | 28 FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL); |
29 | 29 |
30 if (!getter.is_null()) { | 30 if (!getter.is_null()) { |
31 // Call the JavaScript getter with the receiver on the stack. | 31 // Call the JavaScript getter with the receiver on the stack. |
32 if (IC::TypeToMap(*type, masm->isolate())->IsJSGlobalObjectMap()) { | 32 if (IC::TypeToMap(*type, masm->isolate())->IsJSGlobalObjectMap()) { |
33 // Swap in the global receiver. | 33 // Swap in the global receiver. |
34 __ ldr(receiver, | 34 __ LoadP(receiver, |
35 FieldMemOperand(receiver, JSGlobalObject::kGlobalProxyOffset)); | 35 FieldMemOperand(receiver, JSGlobalObject::kGlobalProxyOffset)); |
36 } | 36 } |
37 __ push(receiver); | 37 __ push(receiver); |
38 ParameterCount actual(0); | 38 ParameterCount actual(0); |
39 ParameterCount expected(getter); | 39 ParameterCount expected(getter); |
40 __ InvokeFunction(getter, expected, actual, CALL_FUNCTION, | 40 __ InvokeFunction(getter, expected, actual, CALL_FUNCTION, |
41 NullCallWrapper()); | 41 NullCallWrapper()); |
42 } else { | 42 } else { |
43 // If we generate a global code snippet for deoptimization only, remember | 43 // If we generate a global code snippet for deoptimization only, remember |
44 // the place to continue after deoptimization. | 44 // the place to continue after deoptimization. |
45 masm->isolate()->heap()->SetGetterStubDeoptPCOffset(masm->pc_offset()); | 45 masm->isolate()->heap()->SetGetterStubDeoptPCOffset(masm->pc_offset()); |
46 } | 46 } |
47 | 47 |
48 // Restore context register. | 48 // Restore context register. |
49 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 49 __ LoadP(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
50 } | 50 } |
51 __ Ret(); | 51 __ Ret(); |
52 } | 52 } |
53 | 53 |
54 | 54 |
55 void NamedStoreHandlerCompiler::GenerateStoreViaSetter( | 55 void NamedStoreHandlerCompiler::GenerateStoreViaSetter( |
56 MacroAssembler* masm, Handle<HeapType> type, Register receiver, | 56 MacroAssembler* masm, Handle<HeapType> type, Register receiver, |
57 Handle<JSFunction> setter) { | 57 Handle<JSFunction> setter) { |
58 // ----------- S t a t e ------------- | 58 // ----------- S t a t e ------------- |
59 // -- lr : return address | 59 // -- lr : return address |
60 // ----------------------------------- | 60 // ----------------------------------- |
61 { | 61 { |
62 FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL); | 62 FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL); |
63 | 63 |
64 // Save value register, so we can restore it later. | 64 // Save value register, so we can restore it later. |
65 __ push(value()); | 65 __ push(value()); |
66 | 66 |
67 if (!setter.is_null()) { | 67 if (!setter.is_null()) { |
68 // Call the JavaScript setter with receiver and value on the stack. | 68 // Call the JavaScript setter with receiver and value on the stack. |
69 if (IC::TypeToMap(*type, masm->isolate())->IsJSGlobalObjectMap()) { | 69 if (IC::TypeToMap(*type, masm->isolate())->IsJSGlobalObjectMap()) { |
70 // Swap in the global receiver. | 70 // Swap in the global receiver. |
71 __ ldr(receiver, | 71 __ LoadP(receiver, |
72 FieldMemOperand(receiver, JSGlobalObject::kGlobalProxyOffset)); | 72 FieldMemOperand(receiver, JSGlobalObject::kGlobalProxyOffset)); |
73 } | 73 } |
74 __ Push(receiver, value()); | 74 __ Push(receiver, value()); |
75 ParameterCount actual(1); | 75 ParameterCount actual(1); |
76 ParameterCount expected(setter); | 76 ParameterCount expected(setter); |
77 __ InvokeFunction(setter, expected, actual, CALL_FUNCTION, | 77 __ InvokeFunction(setter, expected, actual, CALL_FUNCTION, |
78 NullCallWrapper()); | 78 NullCallWrapper()); |
79 } else { | 79 } else { |
80 // If we generate a global code snippet for deoptimization only, remember | 80 // If we generate a global code snippet for deoptimization only, remember |
81 // the place to continue after deoptimization. | 81 // the place to continue after deoptimization. |
82 masm->isolate()->heap()->SetSetterStubDeoptPCOffset(masm->pc_offset()); | 82 masm->isolate()->heap()->SetSetterStubDeoptPCOffset(masm->pc_offset()); |
83 } | 83 } |
84 | 84 |
85 // We have to return the passed value, not the return value of the setter. | 85 // We have to return the passed value, not the return value of the setter. |
86 __ pop(r0); | 86 __ pop(r3); |
87 | 87 |
88 // Restore context register. | 88 // Restore context register. |
89 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 89 __ LoadP(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
90 } | 90 } |
91 __ Ret(); | 91 __ Ret(); |
92 } | 92 } |
93 | 93 |
94 | 94 |
95 void PropertyHandlerCompiler::GenerateDictionaryNegativeLookup( | 95 void PropertyHandlerCompiler::GenerateDictionaryNegativeLookup( |
96 MacroAssembler* masm, Label* miss_label, Register receiver, | 96 MacroAssembler* masm, Label* miss_label, Register receiver, |
97 Handle<Name> name, Register scratch0, Register scratch1) { | 97 Handle<Name> name, Register scratch0, Register scratch1) { |
98 DCHECK(name->IsUniqueName()); | 98 DCHECK(name->IsUniqueName()); |
99 DCHECK(!receiver.is(scratch0)); | 99 DCHECK(!receiver.is(scratch0)); |
100 Counters* counters = masm->isolate()->counters(); | 100 Counters* counters = masm->isolate()->counters(); |
101 __ IncrementCounter(counters->negative_lookups(), 1, scratch0, scratch1); | 101 __ IncrementCounter(counters->negative_lookups(), 1, scratch0, scratch1); |
102 __ IncrementCounter(counters->negative_lookups_miss(), 1, scratch0, scratch1); | 102 __ IncrementCounter(counters->negative_lookups_miss(), 1, scratch0, scratch1); |
103 | 103 |
104 Label done; | 104 Label done; |
105 | 105 |
106 const int kInterceptorOrAccessCheckNeededMask = | 106 const int kInterceptorOrAccessCheckNeededMask = |
107 (1 << Map::kHasNamedInterceptor) | (1 << Map::kIsAccessCheckNeeded); | 107 (1 << Map::kHasNamedInterceptor) | (1 << Map::kIsAccessCheckNeeded); |
108 | 108 |
109 // Bail out if the receiver has a named interceptor or requires access checks. | 109 // Bail out if the receiver has a named interceptor or requires access checks. |
110 Register map = scratch1; | 110 Register map = scratch1; |
111 __ ldr(map, FieldMemOperand(receiver, HeapObject::kMapOffset)); | 111 __ LoadP(map, FieldMemOperand(receiver, HeapObject::kMapOffset)); |
112 __ ldrb(scratch0, FieldMemOperand(map, Map::kBitFieldOffset)); | 112 __ lbz(scratch0, FieldMemOperand(map, Map::kBitFieldOffset)); |
113 __ tst(scratch0, Operand(kInterceptorOrAccessCheckNeededMask)); | 113 __ andi(r0, scratch0, Operand(kInterceptorOrAccessCheckNeededMask)); |
114 __ b(ne, miss_label); | 114 __ bne(miss_label, cr0); |
115 | 115 |
116 // Check that receiver is a JSObject. | 116 // Check that receiver is a JSObject. |
117 __ ldrb(scratch0, FieldMemOperand(map, Map::kInstanceTypeOffset)); | 117 __ lbz(scratch0, FieldMemOperand(map, Map::kInstanceTypeOffset)); |
118 __ cmp(scratch0, Operand(FIRST_SPEC_OBJECT_TYPE)); | 118 __ cmpi(scratch0, Operand(FIRST_SPEC_OBJECT_TYPE)); |
119 __ b(lt, miss_label); | 119 __ blt(miss_label); |
120 | 120 |
121 // Load properties array. | 121 // Load properties array. |
122 Register properties = scratch0; | 122 Register properties = scratch0; |
123 __ ldr(properties, FieldMemOperand(receiver, JSObject::kPropertiesOffset)); | 123 __ LoadP(properties, FieldMemOperand(receiver, JSObject::kPropertiesOffset)); |
124 // Check that the properties array is a dictionary. | 124 // Check that the properties array is a dictionary. |
125 __ ldr(map, FieldMemOperand(properties, HeapObject::kMapOffset)); | 125 __ LoadP(map, FieldMemOperand(properties, HeapObject::kMapOffset)); |
126 Register tmp = properties; | 126 Register tmp = properties; |
127 __ LoadRoot(tmp, Heap::kHashTableMapRootIndex); | 127 __ LoadRoot(tmp, Heap::kHashTableMapRootIndex); |
128 __ cmp(map, tmp); | 128 __ cmp(map, tmp); |
129 __ b(ne, miss_label); | 129 __ bne(miss_label); |
130 | 130 |
131 // Restore the temporarily used register. | 131 // Restore the temporarily used register. |
132 __ ldr(properties, FieldMemOperand(receiver, JSObject::kPropertiesOffset)); | 132 __ LoadP(properties, FieldMemOperand(receiver, JSObject::kPropertiesOffset)); |
133 | 133 |
134 | 134 |
135 NameDictionaryLookupStub::GenerateNegativeLookup( | 135 NameDictionaryLookupStub::GenerateNegativeLookup( |
136 masm, miss_label, &done, receiver, properties, name, scratch1); | 136 masm, miss_label, &done, receiver, properties, name, scratch1); |
137 __ bind(&done); | 137 __ bind(&done); |
138 __ DecrementCounter(counters->negative_lookups_miss(), 1, scratch0, scratch1); | 138 __ DecrementCounter(counters->negative_lookups_miss(), 1, scratch0, scratch1); |
139 } | 139 } |
140 | 140 |
141 | 141 |
142 void NamedLoadHandlerCompiler::GenerateDirectLoadGlobalFunctionPrototype( | 142 void NamedLoadHandlerCompiler::GenerateDirectLoadGlobalFunctionPrototype( |
143 MacroAssembler* masm, int index, Register prototype, Label* miss) { | 143 MacroAssembler* masm, int index, Register prototype, Label* miss) { |
144 Isolate* isolate = masm->isolate(); | 144 Isolate* isolate = masm->isolate(); |
145 // Get the global function with the given index. | 145 // Get the global function with the given index. |
146 Handle<JSFunction> function( | 146 Handle<JSFunction> function( |
147 JSFunction::cast(isolate->native_context()->get(index))); | 147 JSFunction::cast(isolate->native_context()->get(index))); |
148 | 148 |
149 // Check we're still in the same context. | 149 // Check we're still in the same context. |
150 Register scratch = prototype; | 150 Register scratch = prototype; |
151 const int offset = Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX); | 151 const int offset = Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX); |
152 __ ldr(scratch, MemOperand(cp, offset)); | 152 __ LoadP(scratch, MemOperand(cp, offset)); |
153 __ ldr(scratch, FieldMemOperand(scratch, GlobalObject::kNativeContextOffset)); | 153 __ LoadP(scratch, |
154 __ ldr(scratch, MemOperand(scratch, Context::SlotOffset(index))); | 154 FieldMemOperand(scratch, GlobalObject::kNativeContextOffset)); |
| 155 __ LoadP(scratch, MemOperand(scratch, Context::SlotOffset(index))); |
155 __ Move(ip, function); | 156 __ Move(ip, function); |
156 __ cmp(ip, scratch); | 157 __ cmp(ip, scratch); |
157 __ b(ne, miss); | 158 __ bne(miss); |
158 | 159 |
159 // Load its initial map. The global functions all have initial maps. | 160 // Load its initial map. The global functions all have initial maps. |
160 __ Move(prototype, Handle<Map>(function->initial_map())); | 161 __ Move(prototype, Handle<Map>(function->initial_map())); |
161 // Load the prototype from the initial map. | 162 // Load the prototype from the initial map. |
162 __ ldr(prototype, FieldMemOperand(prototype, Map::kPrototypeOffset)); | 163 __ LoadP(prototype, FieldMemOperand(prototype, Map::kPrototypeOffset)); |
163 } | 164 } |
164 | 165 |
165 | 166 |
166 void NamedLoadHandlerCompiler::GenerateLoadFunctionPrototype( | 167 void NamedLoadHandlerCompiler::GenerateLoadFunctionPrototype( |
167 MacroAssembler* masm, Register receiver, Register scratch1, | 168 MacroAssembler* masm, Register receiver, Register scratch1, |
168 Register scratch2, Label* miss_label) { | 169 Register scratch2, Label* miss_label) { |
169 __ TryGetFunctionPrototype(receiver, scratch1, scratch2, miss_label); | 170 __ TryGetFunctionPrototype(receiver, scratch1, scratch2, miss_label); |
170 __ mov(r0, scratch1); | 171 __ mr(r3, scratch1); |
171 __ Ret(); | 172 __ Ret(); |
172 } | 173 } |
173 | 174 |
174 | 175 |
175 // Generate code to check that a global property cell is empty. Create | 176 // Generate code to check that a global property cell is empty. Create |
176 // the property cell at compilation time if no cell exists for the | 177 // the property cell at compilation time if no cell exists for the |
177 // property. | 178 // property. |
178 void PropertyHandlerCompiler::GenerateCheckPropertyCell( | 179 void PropertyHandlerCompiler::GenerateCheckPropertyCell( |
179 MacroAssembler* masm, Handle<JSGlobalObject> global, Handle<Name> name, | 180 MacroAssembler* masm, Handle<JSGlobalObject> global, Handle<Name> name, |
180 Register scratch, Label* miss) { | 181 Register scratch, Label* miss) { |
181 Handle<Cell> cell = JSGlobalObject::EnsurePropertyCell(global, name); | 182 Handle<Cell> cell = JSGlobalObject::EnsurePropertyCell(global, name); |
182 DCHECK(cell->value()->IsTheHole()); | 183 DCHECK(cell->value()->IsTheHole()); |
183 __ mov(scratch, Operand(cell)); | 184 __ mov(scratch, Operand(cell)); |
184 __ ldr(scratch, FieldMemOperand(scratch, Cell::kValueOffset)); | 185 __ LoadP(scratch, FieldMemOperand(scratch, Cell::kValueOffset)); |
185 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); | 186 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); |
186 __ cmp(scratch, ip); | 187 __ cmp(scratch, ip); |
187 __ b(ne, miss); | 188 __ bne(miss); |
188 } | 189 } |
189 | 190 |
190 | 191 |
191 static void PushInterceptorArguments(MacroAssembler* masm, Register receiver, | 192 static void PushInterceptorArguments(MacroAssembler* masm, Register receiver, |
192 Register holder, Register name, | 193 Register holder, Register name, |
193 Handle<JSObject> holder_obj) { | 194 Handle<JSObject> holder_obj) { |
194 STATIC_ASSERT(NamedLoadHandlerCompiler::kInterceptorArgsNameIndex == 0); | 195 STATIC_ASSERT(NamedLoadHandlerCompiler::kInterceptorArgsNameIndex == 0); |
195 STATIC_ASSERT(NamedLoadHandlerCompiler::kInterceptorArgsInfoIndex == 1); | 196 STATIC_ASSERT(NamedLoadHandlerCompiler::kInterceptorArgsInfoIndex == 1); |
196 STATIC_ASSERT(NamedLoadHandlerCompiler::kInterceptorArgsThisIndex == 2); | 197 STATIC_ASSERT(NamedLoadHandlerCompiler::kInterceptorArgsThisIndex == 2); |
197 STATIC_ASSERT(NamedLoadHandlerCompiler::kInterceptorArgsHolderIndex == 3); | 198 STATIC_ASSERT(NamedLoadHandlerCompiler::kInterceptorArgsHolderIndex == 3); |
(...skipping 28 matching lines...) Expand all Loading... |
226 // Write the arguments to stack frame. | 227 // Write the arguments to stack frame. |
227 for (int i = 0; i < argc; i++) { | 228 for (int i = 0; i < argc; i++) { |
228 Register arg = values[argc - 1 - i]; | 229 Register arg = values[argc - 1 - i]; |
229 DCHECK(!receiver.is(arg)); | 230 DCHECK(!receiver.is(arg)); |
230 DCHECK(!scratch_in.is(arg)); | 231 DCHECK(!scratch_in.is(arg)); |
231 __ push(arg); | 232 __ push(arg); |
232 } | 233 } |
233 DCHECK(optimization.is_simple_api_call()); | 234 DCHECK(optimization.is_simple_api_call()); |
234 | 235 |
235 // Abi for CallApiFunctionStub. | 236 // Abi for CallApiFunctionStub. |
236 Register callee = r0; | 237 Register callee = r3; |
237 Register call_data = r4; | 238 Register call_data = r7; |
238 Register holder = r2; | 239 Register holder = r5; |
239 Register api_function_address = r1; | 240 Register api_function_address = r4; |
240 | 241 |
241 // Put holder in place. | 242 // Put holder in place. |
242 CallOptimization::HolderLookup holder_lookup; | 243 CallOptimization::HolderLookup holder_lookup; |
243 Handle<JSObject> api_holder = | 244 Handle<JSObject> api_holder = |
244 optimization.LookupHolderOfExpectedType(receiver_map, &holder_lookup); | 245 optimization.LookupHolderOfExpectedType(receiver_map, &holder_lookup); |
245 switch (holder_lookup) { | 246 switch (holder_lookup) { |
246 case CallOptimization::kHolderIsReceiver: | 247 case CallOptimization::kHolderIsReceiver: |
247 __ Move(holder, receiver); | 248 __ Move(holder, receiver); |
248 break; | 249 break; |
249 case CallOptimization::kHolderFound: | 250 case CallOptimization::kHolderFound: |
250 __ Move(holder, api_holder); | 251 __ Move(holder, api_holder); |
251 break; | 252 break; |
252 case CallOptimization::kHolderNotFound: | 253 case CallOptimization::kHolderNotFound: |
253 UNREACHABLE(); | 254 UNREACHABLE(); |
254 break; | 255 break; |
255 } | 256 } |
256 | 257 |
257 Isolate* isolate = masm->isolate(); | 258 Isolate* isolate = masm->isolate(); |
258 Handle<JSFunction> function = optimization.constant_function(); | 259 Handle<JSFunction> function = optimization.constant_function(); |
259 Handle<CallHandlerInfo> api_call_info = optimization.api_call_info(); | 260 Handle<CallHandlerInfo> api_call_info = optimization.api_call_info(); |
260 Handle<Object> call_data_obj(api_call_info->data(), isolate); | 261 Handle<Object> call_data_obj(api_call_info->data(), isolate); |
261 | 262 |
262 // Put callee in place. | 263 // Put callee in place. |
263 __ Move(callee, function); | 264 __ Move(callee, function); |
264 | 265 |
265 bool call_data_undefined = false; | 266 bool call_data_undefined = false; |
266 // Put call_data in place. | 267 // Put call_data in place. |
267 if (isolate->heap()->InNewSpace(*call_data_obj)) { | 268 if (isolate->heap()->InNewSpace(*call_data_obj)) { |
268 __ Move(call_data, api_call_info); | 269 __ Move(call_data, api_call_info); |
269 __ ldr(call_data, FieldMemOperand(call_data, CallHandlerInfo::kDataOffset)); | 270 __ LoadP(call_data, |
| 271 FieldMemOperand(call_data, CallHandlerInfo::kDataOffset)); |
270 } else if (call_data_obj->IsUndefined()) { | 272 } else if (call_data_obj->IsUndefined()) { |
271 call_data_undefined = true; | 273 call_data_undefined = true; |
272 __ LoadRoot(call_data, Heap::kUndefinedValueRootIndex); | 274 __ LoadRoot(call_data, Heap::kUndefinedValueRootIndex); |
273 } else { | 275 } else { |
274 __ Move(call_data, call_data_obj); | 276 __ Move(call_data, call_data_obj); |
275 } | 277 } |
276 | 278 |
277 // Put api_function_address in place. | 279 // Put api_function_address in place. |
278 Address function_address = v8::ToCData<Address>(api_call_info->callback()); | 280 Address function_address = v8::ToCData<Address>(api_call_info->callback()); |
279 ApiFunction fun(function_address); | 281 ApiFunction fun(function_address); |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
331 __ mov(this->name(), Operand(name)); | 333 __ mov(this->name(), Operand(name)); |
332 __ mov(StoreTransitionDescriptor::MapRegister(), Operand(transition)); | 334 __ mov(StoreTransitionDescriptor::MapRegister(), Operand(transition)); |
333 } | 335 } |
334 | 336 |
335 | 337 |
336 void NamedStoreHandlerCompiler::GenerateConstantCheck(Object* constant, | 338 void NamedStoreHandlerCompiler::GenerateConstantCheck(Object* constant, |
337 Register value_reg, | 339 Register value_reg, |
338 Label* miss_label) { | 340 Label* miss_label) { |
339 __ Move(scratch1(), handle(constant, isolate())); | 341 __ Move(scratch1(), handle(constant, isolate())); |
340 __ cmp(value_reg, scratch1()); | 342 __ cmp(value_reg, scratch1()); |
341 __ b(ne, miss_label); | 343 __ bne(miss_label); |
342 } | 344 } |
343 | 345 |
344 | 346 |
345 void NamedStoreHandlerCompiler::GenerateFieldTypeChecks(HeapType* field_type, | 347 void NamedStoreHandlerCompiler::GenerateFieldTypeChecks(HeapType* field_type, |
346 Register value_reg, | 348 Register value_reg, |
347 Label* miss_label) { | 349 Label* miss_label) { |
348 __ JumpIfSmi(value_reg, miss_label); | 350 __ JumpIfSmi(value_reg, miss_label); |
349 HeapType::Iterator<Map> it = field_type->Classes(); | 351 HeapType::Iterator<Map> it = field_type->Classes(); |
350 if (!it.Done()) { | 352 if (!it.Done()) { |
351 __ ldr(scratch1(), FieldMemOperand(value_reg, HeapObject::kMapOffset)); | 353 __ LoadP(scratch1(), FieldMemOperand(value_reg, HeapObject::kMapOffset)); |
352 Label do_store; | 354 Label do_store; |
353 while (true) { | 355 while (true) { |
354 __ CompareMap(scratch1(), it.Current(), &do_store); | 356 __ CompareMap(scratch1(), it.Current(), &do_store); |
355 it.Advance(); | 357 it.Advance(); |
356 if (it.Done()) { | 358 if (it.Done()) { |
357 __ b(ne, miss_label); | 359 __ bne(miss_label); |
358 break; | 360 break; |
359 } | 361 } |
360 __ b(eq, &do_store); | 362 __ beq(&do_store); |
361 } | 363 } |
362 __ bind(&do_store); | 364 __ bind(&do_store); |
363 } | 365 } |
364 } | 366 } |
365 | 367 |
366 | 368 |
367 Register PropertyHandlerCompiler::CheckPrototypes( | 369 Register PropertyHandlerCompiler::CheckPrototypes( |
368 Register object_reg, Register holder_reg, Register scratch1, | 370 Register object_reg, Register holder_reg, Register scratch1, |
369 Register scratch2, Handle<Name> name, Label* miss, | 371 Register scratch2, Handle<Name> name, Label* miss, |
370 PrototypeCheckType check) { | 372 PrototypeCheckType check) { |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
404 DCHECK(name->IsString()); | 406 DCHECK(name->IsString()); |
405 name = factory()->InternalizeString(Handle<String>::cast(name)); | 407 name = factory()->InternalizeString(Handle<String>::cast(name)); |
406 } | 408 } |
407 DCHECK(current.is_null() || | 409 DCHECK(current.is_null() || |
408 current->property_dictionary()->FindEntry(name) == | 410 current->property_dictionary()->FindEntry(name) == |
409 NameDictionary::kNotFound); | 411 NameDictionary::kNotFound); |
410 | 412 |
411 GenerateDictionaryNegativeLookup(masm(), miss, reg, name, scratch1, | 413 GenerateDictionaryNegativeLookup(masm(), miss, reg, name, scratch1, |
412 scratch2); | 414 scratch2); |
413 | 415 |
414 __ ldr(scratch1, FieldMemOperand(reg, HeapObject::kMapOffset)); | 416 __ LoadP(scratch1, FieldMemOperand(reg, HeapObject::kMapOffset)); |
415 reg = holder_reg; // From now on the object will be in holder_reg. | 417 reg = holder_reg; // From now on the object will be in holder_reg. |
416 __ ldr(reg, FieldMemOperand(scratch1, Map::kPrototypeOffset)); | 418 __ LoadP(reg, FieldMemOperand(scratch1, Map::kPrototypeOffset)); |
417 } else { | 419 } else { |
418 Register map_reg = scratch1; | 420 Register map_reg = scratch1; |
419 if (depth != 1 || check == CHECK_ALL_MAPS) { | 421 if (depth != 1 || check == CHECK_ALL_MAPS) { |
420 // CheckMap implicitly loads the map of |reg| into |map_reg|. | 422 // CheckMap implicitly loads the map of |reg| into |map_reg|. |
421 __ CheckMap(reg, map_reg, current_map, miss, DONT_DO_SMI_CHECK); | 423 __ CheckMap(reg, map_reg, current_map, miss, DONT_DO_SMI_CHECK); |
422 } else { | 424 } else { |
423 __ ldr(map_reg, FieldMemOperand(reg, HeapObject::kMapOffset)); | 425 __ LoadP(map_reg, FieldMemOperand(reg, HeapObject::kMapOffset)); |
424 } | 426 } |
425 | 427 |
426 // Check access rights to the global object. This has to happen after | 428 // Check access rights to the global object. This has to happen after |
427 // the map check so that we know that the object is actually a global | 429 // the map check so that we know that the object is actually a global |
428 // object. | 430 // object. |
429 // This allows us to install generated handlers for accesses to the | 431 // This allows us to install generated handlers for accesses to the |
430 // global proxy (as opposed to using slow ICs). See corresponding code | 432 // global proxy (as opposed to using slow ICs). See corresponding code |
431 // in LookupForRead(). | 433 // in LookupForRead(). |
432 if (current_map->IsJSGlobalProxyMap()) { | 434 if (current_map->IsJSGlobalProxyMap()) { |
433 __ CheckAccessGlobalProxy(reg, scratch2, miss); | 435 __ CheckAccessGlobalProxy(reg, scratch2, miss); |
434 } else if (current_map->IsJSGlobalObjectMap()) { | 436 } else if (current_map->IsJSGlobalObjectMap()) { |
435 GenerateCheckPropertyCell(masm(), Handle<JSGlobalObject>::cast(current), | 437 GenerateCheckPropertyCell(masm(), Handle<JSGlobalObject>::cast(current), |
436 name, scratch2, miss); | 438 name, scratch2, miss); |
437 } | 439 } |
438 | 440 |
439 reg = holder_reg; // From now on the object will be in holder_reg. | 441 reg = holder_reg; // From now on the object will be in holder_reg. |
440 | 442 |
441 // Two possible reasons for loading the prototype from the map: | 443 // Two possible reasons for loading the prototype from the map: |
442 // (1) Can't store references to new space in code. | 444 // (1) Can't store references to new space in code. |
443 // (2) Handler is shared for all receivers with the same prototype | 445 // (2) Handler is shared for all receivers with the same prototype |
444 // map (but not necessarily the same prototype instance). | 446 // map (but not necessarily the same prototype instance). |
445 bool load_prototype_from_map = | 447 bool load_prototype_from_map = |
446 heap()->InNewSpace(*prototype) || depth == 1; | 448 heap()->InNewSpace(*prototype) || depth == 1; |
447 if (load_prototype_from_map) { | 449 if (load_prototype_from_map) { |
448 __ ldr(reg, FieldMemOperand(map_reg, Map::kPrototypeOffset)); | 450 __ LoadP(reg, FieldMemOperand(map_reg, Map::kPrototypeOffset)); |
449 } else { | 451 } else { |
450 __ mov(reg, Operand(prototype)); | 452 __ mov(reg, Operand(prototype)); |
451 } | 453 } |
452 } | 454 } |
453 | 455 |
454 // Go to the next object in the prototype chain. | 456 // Go to the next object in the prototype chain. |
455 current = prototype; | 457 current = prototype; |
456 current_map = handle(current->map()); | 458 current_map = handle(current->map()); |
457 } | 459 } |
458 | 460 |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
493 __ b(&success); | 495 __ b(&success); |
494 GenerateRestoreName(miss, name); | 496 GenerateRestoreName(miss, name); |
495 TailCallBuiltin(masm(), MissBuiltin(kind())); | 497 TailCallBuiltin(masm(), MissBuiltin(kind())); |
496 __ bind(&success); | 498 __ bind(&success); |
497 } | 499 } |
498 } | 500 } |
499 | 501 |
500 | 502 |
501 void NamedLoadHandlerCompiler::GenerateLoadConstant(Handle<Object> value) { | 503 void NamedLoadHandlerCompiler::GenerateLoadConstant(Handle<Object> value) { |
502 // Return the constant value. | 504 // Return the constant value. |
503 __ Move(r0, value); | 505 __ Move(r3, value); |
504 __ Ret(); | 506 __ Ret(); |
505 } | 507 } |
506 | 508 |
507 | 509 |
508 void NamedLoadHandlerCompiler::GenerateLoadCallback( | 510 void NamedLoadHandlerCompiler::GenerateLoadCallback( |
509 Register reg, Handle<ExecutableAccessorInfo> callback) { | 511 Register reg, Handle<ExecutableAccessorInfo> callback) { |
510 // Build AccessorInfo::args_ list on the stack and push property name below | 512 // Build AccessorInfo::args_ list on the stack and push property name below |
511 // the exit frame to make GC aware of them and store pointers to them. | 513 // the exit frame to make GC aware of them and store pointers to them. |
512 STATIC_ASSERT(PropertyCallbackArguments::kHolderIndex == 0); | 514 STATIC_ASSERT(PropertyCallbackArguments::kHolderIndex == 0); |
513 STATIC_ASSERT(PropertyCallbackArguments::kIsolateIndex == 1); | 515 STATIC_ASSERT(PropertyCallbackArguments::kIsolateIndex == 1); |
514 STATIC_ASSERT(PropertyCallbackArguments::kReturnValueDefaultValueIndex == 2); | 516 STATIC_ASSERT(PropertyCallbackArguments::kReturnValueDefaultValueIndex == 2); |
515 STATIC_ASSERT(PropertyCallbackArguments::kReturnValueOffset == 3); | 517 STATIC_ASSERT(PropertyCallbackArguments::kReturnValueOffset == 3); |
516 STATIC_ASSERT(PropertyCallbackArguments::kDataIndex == 4); | 518 STATIC_ASSERT(PropertyCallbackArguments::kDataIndex == 4); |
517 STATIC_ASSERT(PropertyCallbackArguments::kThisIndex == 5); | 519 STATIC_ASSERT(PropertyCallbackArguments::kThisIndex == 5); |
518 STATIC_ASSERT(PropertyCallbackArguments::kArgsLength == 6); | 520 STATIC_ASSERT(PropertyCallbackArguments::kArgsLength == 6); |
519 DCHECK(!scratch2().is(reg)); | 521 DCHECK(!scratch2().is(reg)); |
520 DCHECK(!scratch3().is(reg)); | 522 DCHECK(!scratch3().is(reg)); |
521 DCHECK(!scratch4().is(reg)); | 523 DCHECK(!scratch4().is(reg)); |
522 __ push(receiver()); | 524 __ push(receiver()); |
523 if (heap()->InNewSpace(callback->data())) { | 525 if (heap()->InNewSpace(callback->data())) { |
524 __ Move(scratch3(), callback); | 526 __ Move(scratch3(), callback); |
525 __ ldr(scratch3(), | 527 __ LoadP(scratch3(), |
526 FieldMemOperand(scratch3(), ExecutableAccessorInfo::kDataOffset)); | 528 FieldMemOperand(scratch3(), ExecutableAccessorInfo::kDataOffset)); |
527 } else { | 529 } else { |
528 __ Move(scratch3(), Handle<Object>(callback->data(), isolate())); | 530 __ Move(scratch3(), Handle<Object>(callback->data(), isolate())); |
529 } | 531 } |
530 __ push(scratch3()); | 532 __ push(scratch3()); |
531 __ LoadRoot(scratch3(), Heap::kUndefinedValueRootIndex); | 533 __ LoadRoot(scratch3(), Heap::kUndefinedValueRootIndex); |
532 __ mov(scratch4(), scratch3()); | 534 __ mr(scratch4(), scratch3()); |
533 __ Push(scratch3(), scratch4()); | 535 __ Push(scratch3(), scratch4()); |
534 __ mov(scratch4(), Operand(ExternalReference::isolate_address(isolate()))); | 536 __ mov(scratch4(), Operand(ExternalReference::isolate_address(isolate()))); |
535 __ Push(scratch4(), reg); | 537 __ Push(scratch4(), reg); |
536 __ mov(scratch2(), sp); // scratch2 = PropertyAccessorInfo::args_ | |
537 __ push(name()); | 538 __ push(name()); |
538 | 539 |
539 // Abi for CallApiGetter | 540 // Abi for CallApiGetter |
540 Register getter_address_reg = ApiGetterDescriptor::function_address(); | 541 Register getter_address_reg = ApiGetterDescriptor::function_address(); |
541 | 542 |
542 Address getter_address = v8::ToCData<Address>(callback->getter()); | 543 Address getter_address = v8::ToCData<Address>(callback->getter()); |
543 ApiFunction fun(getter_address); | 544 ApiFunction fun(getter_address); |
544 ExternalReference::Type type = ExternalReference::DIRECT_GETTER_CALL; | 545 ExternalReference::Type type = ExternalReference::DIRECT_GETTER_CALL; |
545 ExternalReference ref = ExternalReference(&fun, type, isolate()); | 546 ExternalReference ref = ExternalReference(&fun, type, isolate()); |
546 __ mov(getter_address_reg, Operand(ref)); | 547 __ mov(getter_address_reg, Operand(ref)); |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
583 // interceptor's holder has been compiled before (see a caller | 584 // interceptor's holder has been compiled before (see a caller |
584 // of this method.) | 585 // of this method.) |
585 CompileCallLoadPropertyWithInterceptor( | 586 CompileCallLoadPropertyWithInterceptor( |
586 masm(), receiver(), holder_reg, this->name(), holder(), | 587 masm(), receiver(), holder_reg, this->name(), holder(), |
587 IC::kLoadPropertyWithInterceptorOnly); | 588 IC::kLoadPropertyWithInterceptorOnly); |
588 | 589 |
589 // Check if interceptor provided a value for property. If it's | 590 // Check if interceptor provided a value for property. If it's |
590 // the case, return immediately. | 591 // the case, return immediately. |
591 Label interceptor_failed; | 592 Label interceptor_failed; |
592 __ LoadRoot(scratch1(), Heap::kNoInterceptorResultSentinelRootIndex); | 593 __ LoadRoot(scratch1(), Heap::kNoInterceptorResultSentinelRootIndex); |
593 __ cmp(r0, scratch1()); | 594 __ cmp(r3, scratch1()); |
594 __ b(eq, &interceptor_failed); | 595 __ beq(&interceptor_failed); |
595 frame_scope.GenerateLeaveFrame(); | 596 frame_scope.GenerateLeaveFrame(); |
596 __ Ret(); | 597 __ Ret(); |
597 | 598 |
598 __ bind(&interceptor_failed); | 599 __ bind(&interceptor_failed); |
599 __ pop(this->name()); | 600 __ pop(this->name()); |
600 __ pop(holder_reg); | 601 __ pop(holder_reg); |
601 if (must_preserve_receiver_reg) { | 602 if (must_preserve_receiver_reg) { |
602 __ pop(receiver()); | 603 __ pop(receiver()); |
603 } | 604 } |
604 // Leave the internal frame. | 605 // Leave the internal frame. |
(...skipping 15 matching lines...) Expand all Loading... |
620 __ TailCallExternalReference( | 621 __ TailCallExternalReference( |
621 ref, NamedLoadHandlerCompiler::kInterceptorArgsLength, 1); | 622 ref, NamedLoadHandlerCompiler::kInterceptorArgsLength, 1); |
622 } | 623 } |
623 | 624 |
624 | 625 |
625 Handle<Code> NamedStoreHandlerCompiler::CompileStoreCallback( | 626 Handle<Code> NamedStoreHandlerCompiler::CompileStoreCallback( |
626 Handle<JSObject> object, Handle<Name> name, | 627 Handle<JSObject> object, Handle<Name> name, |
627 Handle<ExecutableAccessorInfo> callback) { | 628 Handle<ExecutableAccessorInfo> callback) { |
628 Register holder_reg = Frontend(receiver(), name); | 629 Register holder_reg = Frontend(receiver(), name); |
629 | 630 |
630 __ push(receiver()); // receiver | 631 __ Push(receiver(), holder_reg); // receiver |
631 __ push(holder_reg); | 632 __ mov(ip, Operand(callback)); // callback info |
632 __ mov(ip, Operand(callback)); // callback info | |
633 __ push(ip); | 633 __ push(ip); |
634 __ mov(ip, Operand(name)); | 634 __ mov(ip, Operand(name)); |
635 __ Push(ip, value()); | 635 __ Push(ip, value()); |
636 | 636 |
637 // Do tail-call to the runtime system. | 637 // Do tail-call to the runtime system. |
638 ExternalReference store_callback_property = | 638 ExternalReference store_callback_property = |
639 ExternalReference(IC_Utility(IC::kStoreCallbackProperty), isolate()); | 639 ExternalReference(IC_Utility(IC::kStoreCallbackProperty), isolate()); |
640 __ TailCallExternalReference(store_callback_property, 5, 1); | 640 __ TailCallExternalReference(store_callback_property, 5, 1); |
641 | 641 |
642 // Return the generated code. | 642 // Return the generated code. |
(...skipping 21 matching lines...) Expand all Loading... |
664 | 664 |
665 | 665 |
666 Handle<Code> NamedLoadHandlerCompiler::CompileLoadGlobal( | 666 Handle<Code> NamedLoadHandlerCompiler::CompileLoadGlobal( |
667 Handle<PropertyCell> cell, Handle<Name> name, bool is_configurable) { | 667 Handle<PropertyCell> cell, Handle<Name> name, bool is_configurable) { |
668 Label miss; | 668 Label miss; |
669 FrontendHeader(receiver(), name, &miss); | 669 FrontendHeader(receiver(), name, &miss); |
670 | 670 |
671 // Get the value from the cell. | 671 // Get the value from the cell. |
672 Register result = StoreDescriptor::ValueRegister(); | 672 Register result = StoreDescriptor::ValueRegister(); |
673 __ mov(result, Operand(cell)); | 673 __ mov(result, Operand(cell)); |
674 __ ldr(result, FieldMemOperand(result, Cell::kValueOffset)); | 674 __ LoadP(result, FieldMemOperand(result, Cell::kValueOffset)); |
675 | 675 |
676 // Check for deleted property if property can actually be deleted. | 676 // Check for deleted property if property can actually be deleted. |
677 if (is_configurable) { | 677 if (is_configurable) { |
678 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); | 678 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); |
679 __ cmp(result, ip); | 679 __ cmp(result, ip); |
680 __ b(eq, &miss); | 680 __ beq(&miss); |
681 } | 681 } |
682 | 682 |
683 Counters* counters = isolate()->counters(); | 683 Counters* counters = isolate()->counters(); |
684 __ IncrementCounter(counters->named_load_global_stub(), 1, r1, r3); | 684 __ IncrementCounter(counters->named_load_global_stub(), 1, r4, r6); |
685 __ Ret(); | 685 __ Ret(); |
686 | 686 |
687 FrontendFooter(name, &miss); | 687 FrontendFooter(name, &miss); |
688 | 688 |
689 // Return the generated code. | 689 // Return the generated code. |
690 return GetCode(kind(), Code::NORMAL, name); | 690 return GetCode(kind(), Code::NORMAL, name); |
691 } | 691 } |
692 | 692 |
693 | 693 |
694 #undef __ | 694 #undef __ |
695 } | 695 } |
696 } // namespace v8::internal | 696 } // namespace v8::internal |
697 | 697 |
698 #endif // V8_TARGET_ARCH_ARM | 698 #endif // V8_TARGET_ARCH_ARM |
OLD | NEW |