OLD | NEW |
1 // Copyright 2014 the V8 project authors. All rights reserved. | 1 // Copyright 2015 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 #if V8_TARGET_ARCH_PPC | 5 #if V8_TARGET_ARCH_S390 |
6 | 6 |
7 #include "src/ic/handler-compiler.h" | 7 #include "src/ic/handler-compiler.h" |
8 | 8 |
9 #include "src/field-type.h" | 9 #include "src/field-type.h" |
10 #include "src/ic/call-optimization.h" | 10 #include "src/ic/call-optimization.h" |
11 #include "src/ic/ic.h" | 11 #include "src/ic/ic.h" |
12 #include "src/isolate-inl.h" | 12 #include "src/isolate-inl.h" |
13 | 13 |
14 namespace v8 { | 14 namespace v8 { |
15 namespace internal { | 15 namespace internal { |
16 | 16 |
17 #define __ ACCESS_MASM(masm) | 17 #define __ ACCESS_MASM(masm) |
18 | 18 |
19 | |
20 void NamedLoadHandlerCompiler::GenerateLoadViaGetter( | 19 void NamedLoadHandlerCompiler::GenerateLoadViaGetter( |
21 MacroAssembler* masm, Handle<Map> map, Register receiver, Register holder, | 20 MacroAssembler* masm, Handle<Map> map, Register receiver, Register holder, |
22 int accessor_index, int expected_arguments, Register scratch) { | 21 int accessor_index, int expected_arguments, Register scratch) { |
23 // ----------- S t a t e ------------- | 22 // ----------- S t a t e ------------- |
24 // -- r3 : receiver | 23 // -- r2 : receiver |
25 // -- r5 : name | 24 // -- r4 : name |
26 // -- lr : return address | 25 // -- lr : return address |
27 // ----------------------------------- | 26 // ----------------------------------- |
28 { | 27 { |
29 FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL); | 28 FrameScope scope(masm, StackFrame::INTERNAL); |
30 | 29 |
31 if (accessor_index >= 0) { | 30 if (accessor_index >= 0) { |
32 DCHECK(!holder.is(scratch)); | 31 DCHECK(!holder.is(scratch)); |
33 DCHECK(!receiver.is(scratch)); | 32 DCHECK(!receiver.is(scratch)); |
34 // Call the JavaScript getter with the receiver on the stack. | 33 // Call the JavaScript getter with the receiver on the stack. |
35 if (map->IsJSGlobalObjectMap()) { | 34 if (map->IsJSGlobalObjectMap()) { |
36 // Swap in the global receiver. | 35 // Swap in the global receiver. |
37 __ LoadP(scratch, | 36 __ LoadP(scratch, |
38 FieldMemOperand(receiver, JSGlobalObject::kGlobalProxyOffset)); | 37 FieldMemOperand(receiver, JSGlobalObject::kGlobalProxyOffset)); |
39 receiver = scratch; | 38 receiver = scratch; |
40 } | 39 } |
41 __ push(receiver); | 40 __ Push(receiver); |
42 ParameterCount actual(0); | 41 ParameterCount actual(0); |
43 ParameterCount expected(expected_arguments); | 42 ParameterCount expected(expected_arguments); |
44 __ LoadAccessor(r4, holder, accessor_index, ACCESSOR_GETTER); | 43 __ LoadAccessor(r3, holder, accessor_index, ACCESSOR_GETTER); |
45 __ InvokeFunction(r4, expected, actual, CALL_FUNCTION, | 44 __ InvokeFunction(r3, expected, actual, CALL_FUNCTION, |
46 CheckDebugStepCallWrapper()); | 45 CheckDebugStepCallWrapper()); |
47 } else { | 46 } else { |
48 // If we generate a global code snippet for deoptimization only, remember | 47 // If we generate a global code snippet for deoptimization only, remember |
49 // the place to continue after deoptimization. | 48 // the place to continue after deoptimization. |
50 masm->isolate()->heap()->SetGetterStubDeoptPCOffset(masm->pc_offset()); | 49 masm->isolate()->heap()->SetGetterStubDeoptPCOffset(masm->pc_offset()); |
51 } | 50 } |
52 | 51 |
53 // Restore context register. | 52 // Restore context register. |
54 __ LoadP(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 53 __ LoadP(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
55 } | 54 } |
56 __ Ret(); | 55 __ Ret(); |
57 } | 56 } |
58 | 57 |
59 | |
60 void NamedStoreHandlerCompiler::GenerateStoreViaSetter( | 58 void NamedStoreHandlerCompiler::GenerateStoreViaSetter( |
61 MacroAssembler* masm, Handle<Map> map, Register receiver, Register holder, | 59 MacroAssembler* masm, Handle<Map> map, Register receiver, Register holder, |
62 int accessor_index, int expected_arguments, Register scratch) { | 60 int accessor_index, int expected_arguments, Register scratch) { |
63 // ----------- S t a t e ------------- | 61 // ----------- S t a t e ------------- |
64 // -- lr : return address | 62 // -- lr : return address |
65 // ----------------------------------- | 63 // ----------------------------------- |
66 { | 64 { |
67 FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL); | 65 FrameScope scope(masm, StackFrame::INTERNAL); |
68 | 66 |
69 // Save value register, so we can restore it later. | 67 // Save value register, so we can restore it later. |
70 __ push(value()); | 68 __ Push(value()); |
71 | 69 |
72 if (accessor_index >= 0) { | 70 if (accessor_index >= 0) { |
73 DCHECK(!holder.is(scratch)); | 71 DCHECK(!holder.is(scratch)); |
74 DCHECK(!receiver.is(scratch)); | 72 DCHECK(!receiver.is(scratch)); |
75 DCHECK(!value().is(scratch)); | 73 DCHECK(!value().is(scratch)); |
76 // Call the JavaScript setter with receiver and value on the stack. | 74 // Call the JavaScript setter with receiver and value on the stack. |
77 if (map->IsJSGlobalObjectMap()) { | 75 if (map->IsJSGlobalObjectMap()) { |
78 // Swap in the global receiver. | 76 // Swap in the global receiver. |
79 __ LoadP(scratch, | 77 __ LoadP(scratch, |
80 FieldMemOperand(receiver, JSGlobalObject::kGlobalProxyOffset)); | 78 FieldMemOperand(receiver, JSGlobalObject::kGlobalProxyOffset)); |
81 receiver = scratch; | 79 receiver = scratch; |
82 } | 80 } |
83 __ Push(receiver, value()); | 81 __ Push(receiver, value()); |
84 ParameterCount actual(1); | 82 ParameterCount actual(1); |
85 ParameterCount expected(expected_arguments); | 83 ParameterCount expected(expected_arguments); |
86 __ LoadAccessor(r4, holder, accessor_index, ACCESSOR_SETTER); | 84 __ LoadAccessor(r3, holder, accessor_index, ACCESSOR_SETTER); |
87 __ InvokeFunction(r4, expected, actual, CALL_FUNCTION, | 85 __ InvokeFunction(r3, expected, actual, CALL_FUNCTION, |
88 CheckDebugStepCallWrapper()); | 86 CheckDebugStepCallWrapper()); |
89 } else { | 87 } else { |
90 // If we generate a global code snippet for deoptimization only, remember | 88 // If we generate a global code snippet for deoptimization only, remember |
91 // the place to continue after deoptimization. | 89 // the place to continue after deoptimization. |
92 masm->isolate()->heap()->SetSetterStubDeoptPCOffset(masm->pc_offset()); | 90 masm->isolate()->heap()->SetSetterStubDeoptPCOffset(masm->pc_offset()); |
93 } | 91 } |
94 | 92 |
95 // We have to return the passed value, not the return value of the setter. | 93 // We have to return the passed value, not the return value of the setter. |
96 __ pop(r3); | 94 __ Pop(r2); |
97 | 95 |
98 // Restore context register. | 96 // Restore context register. |
99 __ LoadP(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 97 __ LoadP(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
100 } | 98 } |
101 __ Ret(); | 99 __ Ret(); |
102 } | 100 } |
103 | 101 |
104 | |
105 void PropertyHandlerCompiler::PushVectorAndSlot(Register vector, | 102 void PropertyHandlerCompiler::PushVectorAndSlot(Register vector, |
106 Register slot) { | 103 Register slot) { |
107 MacroAssembler* masm = this->masm(); | 104 MacroAssembler* masm = this->masm(); |
108 __ Push(vector, slot); | 105 __ Push(vector, slot); |
109 } | 106 } |
110 | 107 |
111 | |
112 void PropertyHandlerCompiler::PopVectorAndSlot(Register vector, Register slot) { | 108 void PropertyHandlerCompiler::PopVectorAndSlot(Register vector, Register slot) { |
113 MacroAssembler* masm = this->masm(); | 109 MacroAssembler* masm = this->masm(); |
114 __ Pop(vector, slot); | 110 __ Pop(vector, slot); |
115 } | 111 } |
116 | 112 |
117 | |
118 void PropertyHandlerCompiler::DiscardVectorAndSlot() { | 113 void PropertyHandlerCompiler::DiscardVectorAndSlot() { |
119 MacroAssembler* masm = this->masm(); | 114 MacroAssembler* masm = this->masm(); |
120 // Remove vector and slot. | 115 // Remove vector and slot. |
121 __ addi(sp, sp, Operand(2 * kPointerSize)); | 116 __ la(sp, MemOperand(sp, 2 * kPointerSize)); |
122 } | 117 } |
123 | 118 |
124 | |
125 void PropertyHandlerCompiler::GenerateDictionaryNegativeLookup( | 119 void PropertyHandlerCompiler::GenerateDictionaryNegativeLookup( |
126 MacroAssembler* masm, Label* miss_label, Register receiver, | 120 MacroAssembler* masm, Label* miss_label, Register receiver, |
127 Handle<Name> name, Register scratch0, Register scratch1) { | 121 Handle<Name> name, Register scratch0, Register scratch1) { |
128 DCHECK(name->IsUniqueName()); | 122 DCHECK(name->IsUniqueName()); |
129 DCHECK(!receiver.is(scratch0)); | 123 DCHECK(!receiver.is(scratch0)); |
130 Counters* counters = masm->isolate()->counters(); | 124 Counters* counters = masm->isolate()->counters(); |
131 __ IncrementCounter(counters->negative_lookups(), 1, scratch0, scratch1); | 125 __ IncrementCounter(counters->negative_lookups(), 1, scratch0, scratch1); |
132 __ IncrementCounter(counters->negative_lookups_miss(), 1, scratch0, scratch1); | 126 __ IncrementCounter(counters->negative_lookups_miss(), 1, scratch0, scratch1); |
133 | 127 |
134 Label done; | 128 Label done; |
135 | 129 |
136 const int kInterceptorOrAccessCheckNeededMask = | 130 const int kInterceptorOrAccessCheckNeededMask = |
137 (1 << Map::kHasNamedInterceptor) | (1 << Map::kIsAccessCheckNeeded); | 131 (1 << Map::kHasNamedInterceptor) | (1 << Map::kIsAccessCheckNeeded); |
138 | 132 |
139 // Bail out if the receiver has a named interceptor or requires access checks. | 133 // Bail out if the receiver has a named interceptor or requires access checks. |
140 Register map = scratch1; | 134 Register map = scratch1; |
141 __ LoadP(map, FieldMemOperand(receiver, HeapObject::kMapOffset)); | 135 __ LoadP(map, FieldMemOperand(receiver, HeapObject::kMapOffset)); |
142 __ lbz(scratch0, FieldMemOperand(map, Map::kBitFieldOffset)); | 136 __ LoadlB(scratch0, FieldMemOperand(map, Map::kBitFieldOffset)); |
143 __ andi(r0, scratch0, Operand(kInterceptorOrAccessCheckNeededMask)); | 137 __ AndP(r0, scratch0, Operand(kInterceptorOrAccessCheckNeededMask)); |
144 __ bne(miss_label, cr0); | 138 __ bne(miss_label); |
145 | 139 |
146 // Check that receiver is a JSObject. | 140 // Check that receiver is a JSObject. |
147 __ lbz(scratch0, FieldMemOperand(map, Map::kInstanceTypeOffset)); | 141 // TODO(joransiu): Merge into SI compare |
148 __ cmpi(scratch0, Operand(FIRST_JS_RECEIVER_TYPE)); | 142 __ LoadlB(scratch0, FieldMemOperand(map, Map::kInstanceTypeOffset)); |
| 143 __ CmpP(scratch0, Operand(FIRST_JS_RECEIVER_TYPE)); |
149 __ blt(miss_label); | 144 __ blt(miss_label); |
150 | 145 |
151 // Load properties array. | 146 // Load properties array. |
152 Register properties = scratch0; | 147 Register properties = scratch0; |
153 __ LoadP(properties, FieldMemOperand(receiver, JSObject::kPropertiesOffset)); | 148 __ LoadP(properties, FieldMemOperand(receiver, JSObject::kPropertiesOffset)); |
154 // Check that the properties array is a dictionary. | 149 // Check that the properties array is a dictionary. |
155 __ LoadP(map, FieldMemOperand(properties, HeapObject::kMapOffset)); | 150 __ LoadP(map, FieldMemOperand(properties, HeapObject::kMapOffset)); |
156 Register tmp = properties; | 151 __ CompareRoot(map, Heap::kHashTableMapRootIndex); |
157 __ LoadRoot(tmp, Heap::kHashTableMapRootIndex); | |
158 __ cmp(map, tmp); | |
159 __ bne(miss_label); | 152 __ bne(miss_label); |
160 | 153 |
161 // Restore the temporarily used register. | 154 // Restore the temporarily used register. |
162 __ LoadP(properties, FieldMemOperand(receiver, JSObject::kPropertiesOffset)); | 155 __ LoadP(properties, FieldMemOperand(receiver, JSObject::kPropertiesOffset)); |
163 | 156 |
164 | |
165 NameDictionaryLookupStub::GenerateNegativeLookup( | 157 NameDictionaryLookupStub::GenerateNegativeLookup( |
166 masm, miss_label, &done, receiver, properties, name, scratch1); | 158 masm, miss_label, &done, receiver, properties, name, scratch1); |
167 __ bind(&done); | 159 __ bind(&done); |
168 __ DecrementCounter(counters->negative_lookups_miss(), 1, scratch0, scratch1); | 160 __ DecrementCounter(counters->negative_lookups_miss(), 1, scratch0, scratch1); |
169 } | 161 } |
170 | 162 |
171 | |
172 void NamedLoadHandlerCompiler::GenerateDirectLoadGlobalFunctionPrototype( | 163 void NamedLoadHandlerCompiler::GenerateDirectLoadGlobalFunctionPrototype( |
173 MacroAssembler* masm, int index, Register result, Label* miss) { | 164 MacroAssembler* masm, int index, Register result, Label* miss) { |
174 __ LoadNativeContextSlot(index, result); | 165 __ LoadNativeContextSlot(index, result); |
175 // Load its initial map. The global functions all have initial maps. | 166 // Load its initial map. The global functions all have initial maps. |
176 __ LoadP(result, | 167 __ LoadP(result, |
177 FieldMemOperand(result, JSFunction::kPrototypeOrInitialMapOffset)); | 168 FieldMemOperand(result, JSFunction::kPrototypeOrInitialMapOffset)); |
178 // Load the prototype from the initial map. | 169 // Load the prototype from the initial map. |
179 __ LoadP(result, FieldMemOperand(result, Map::kPrototypeOffset)); | 170 __ LoadP(result, FieldMemOperand(result, Map::kPrototypeOffset)); |
180 } | 171 } |
181 | 172 |
182 | |
183 void NamedLoadHandlerCompiler::GenerateLoadFunctionPrototype( | 173 void NamedLoadHandlerCompiler::GenerateLoadFunctionPrototype( |
184 MacroAssembler* masm, Register receiver, Register scratch1, | 174 MacroAssembler* masm, Register receiver, Register scratch1, |
185 Register scratch2, Label* miss_label) { | 175 Register scratch2, Label* miss_label) { |
186 __ TryGetFunctionPrototype(receiver, scratch1, scratch2, miss_label); | 176 __ TryGetFunctionPrototype(receiver, scratch1, scratch2, miss_label); |
187 __ mr(r3, scratch1); | 177 __ LoadRR(r2, scratch1); |
188 __ Ret(); | 178 __ Ret(); |
189 } | 179 } |
190 | 180 |
191 | |
192 // Generate code to check that a global property cell is empty. Create | 181 // Generate code to check that a global property cell is empty. Create |
193 // the property cell at compilation time if no cell exists for the | 182 // the property cell at compilation time if no cell exists for the |
194 // property. | 183 // property. |
195 void PropertyHandlerCompiler::GenerateCheckPropertyCell( | 184 void PropertyHandlerCompiler::GenerateCheckPropertyCell( |
196 MacroAssembler* masm, Handle<JSGlobalObject> global, Handle<Name> name, | 185 MacroAssembler* masm, Handle<JSGlobalObject> global, Handle<Name> name, |
197 Register scratch, Label* miss) { | 186 Register scratch, Label* miss) { |
198 Handle<PropertyCell> cell = JSGlobalObject::EnsurePropertyCell(global, name); | 187 Handle<PropertyCell> cell = JSGlobalObject::EnsurePropertyCell(global, name); |
199 DCHECK(cell->value()->IsTheHole()); | 188 DCHECK(cell->value()->IsTheHole()); |
200 Handle<WeakCell> weak_cell = masm->isolate()->factory()->NewWeakCell(cell); | 189 Handle<WeakCell> weak_cell = masm->isolate()->factory()->NewWeakCell(cell); |
201 __ LoadWeakValue(scratch, weak_cell, miss); | 190 __ LoadWeakValue(scratch, weak_cell, miss); |
202 __ LoadP(scratch, FieldMemOperand(scratch, PropertyCell::kValueOffset)); | 191 __ LoadP(scratch, FieldMemOperand(scratch, PropertyCell::kValueOffset)); |
203 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); | 192 __ CompareRoot(scratch, Heap::kTheHoleValueRootIndex); |
204 __ cmp(scratch, ip); | |
205 __ bne(miss); | 193 __ bne(miss); |
206 } | 194 } |
207 | 195 |
208 | |
209 static void PushInterceptorArguments(MacroAssembler* masm, Register receiver, | 196 static void PushInterceptorArguments(MacroAssembler* masm, Register receiver, |
210 Register holder, Register name, | 197 Register holder, Register name, |
211 Handle<JSObject> holder_obj) { | 198 Handle<JSObject> holder_obj) { |
212 STATIC_ASSERT(NamedLoadHandlerCompiler::kInterceptorArgsNameIndex == 0); | 199 STATIC_ASSERT(NamedLoadHandlerCompiler::kInterceptorArgsNameIndex == 0); |
213 STATIC_ASSERT(NamedLoadHandlerCompiler::kInterceptorArgsThisIndex == 1); | 200 STATIC_ASSERT(NamedLoadHandlerCompiler::kInterceptorArgsThisIndex == 1); |
214 STATIC_ASSERT(NamedLoadHandlerCompiler::kInterceptorArgsHolderIndex == 2); | 201 STATIC_ASSERT(NamedLoadHandlerCompiler::kInterceptorArgsHolderIndex == 2); |
215 STATIC_ASSERT(NamedLoadHandlerCompiler::kInterceptorArgsLength == 3); | 202 STATIC_ASSERT(NamedLoadHandlerCompiler::kInterceptorArgsLength == 3); |
216 __ push(name); | 203 __ Push(name); |
217 __ push(receiver); | 204 __ Push(receiver); |
218 __ push(holder); | 205 __ Push(holder); |
219 } | 206 } |
220 | 207 |
221 | |
222 static void CompileCallLoadPropertyWithInterceptor( | 208 static void CompileCallLoadPropertyWithInterceptor( |
223 MacroAssembler* masm, Register receiver, Register holder, Register name, | 209 MacroAssembler* masm, Register receiver, Register holder, Register name, |
224 Handle<JSObject> holder_obj, Runtime::FunctionId id) { | 210 Handle<JSObject> holder_obj, Runtime::FunctionId id) { |
225 DCHECK(NamedLoadHandlerCompiler::kInterceptorArgsLength == | 211 DCHECK(NamedLoadHandlerCompiler::kInterceptorArgsLength == |
226 Runtime::FunctionForId(id)->nargs); | 212 Runtime::FunctionForId(id)->nargs); |
227 PushInterceptorArguments(masm, receiver, holder, name, holder_obj); | 213 PushInterceptorArguments(masm, receiver, holder, name, holder_obj); |
228 __ CallRuntime(id); | 214 __ CallRuntime(id); |
229 } | 215 } |
230 | 216 |
231 | |
232 // Generate call to api function. | 217 // Generate call to api function. |
233 void PropertyHandlerCompiler::GenerateApiAccessorCall( | 218 void PropertyHandlerCompiler::GenerateApiAccessorCall( |
234 MacroAssembler* masm, const CallOptimization& optimization, | 219 MacroAssembler* masm, const CallOptimization& optimization, |
235 Handle<Map> receiver_map, Register receiver, Register scratch_in, | 220 Handle<Map> receiver_map, Register receiver, Register scratch_in, |
236 bool is_store, Register store_parameter, Register accessor_holder, | 221 bool is_store, Register store_parameter, Register accessor_holder, |
237 int accessor_index) { | 222 int accessor_index) { |
238 DCHECK(!accessor_holder.is(scratch_in)); | 223 DCHECK(!accessor_holder.is(scratch_in)); |
239 DCHECK(!receiver.is(scratch_in)); | 224 DCHECK(!receiver.is(scratch_in)); |
240 __ push(receiver); | 225 __ Push(receiver); |
241 // Write the arguments to stack frame. | 226 // Write the arguments to stack frame. |
242 if (is_store) { | 227 if (is_store) { |
243 DCHECK(!receiver.is(store_parameter)); | 228 DCHECK(!receiver.is(store_parameter)); |
244 DCHECK(!scratch_in.is(store_parameter)); | 229 DCHECK(!scratch_in.is(store_parameter)); |
245 __ push(store_parameter); | 230 __ Push(store_parameter); |
246 } | 231 } |
247 DCHECK(optimization.is_simple_api_call()); | 232 DCHECK(optimization.is_simple_api_call()); |
248 | 233 |
249 // Abi for CallApiFunctionStub. | 234 // Abi for CallApiFunctionStub. |
250 Register callee = r3; | 235 Register callee = r2; |
251 Register data = r7; | 236 Register data = r6; |
252 Register holder = r5; | 237 Register holder = r4; |
253 Register api_function_address = r4; | 238 Register api_function_address = r3; |
254 | 239 |
255 // Put callee in place. | 240 // Put callee in place. |
256 __ LoadAccessor(callee, accessor_holder, accessor_index, | 241 __ LoadAccessor(callee, accessor_holder, accessor_index, |
257 is_store ? ACCESSOR_SETTER : ACCESSOR_GETTER); | 242 is_store ? ACCESSOR_SETTER : ACCESSOR_GETTER); |
258 | 243 |
259 // Put holder in place. | 244 // Put holder in place. |
260 CallOptimization::HolderLookup holder_lookup; | 245 CallOptimization::HolderLookup holder_lookup; |
261 int holder_depth = 0; | 246 int holder_depth = 0; |
262 optimization.LookupHolderOfExpectedType(receiver_map, &holder_lookup, | 247 optimization.LookupHolderOfExpectedType(receiver_map, &holder_lookup, |
263 &holder_depth); | 248 &holder_depth); |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
313 ExternalReference::Type type = ExternalReference::DIRECT_API_CALL; | 298 ExternalReference::Type type = ExternalReference::DIRECT_API_CALL; |
314 ExternalReference ref = ExternalReference(&fun, type, masm->isolate()); | 299 ExternalReference ref = ExternalReference(&fun, type, masm->isolate()); |
315 __ mov(api_function_address, Operand(ref)); | 300 __ mov(api_function_address, Operand(ref)); |
316 | 301 |
317 // Jump to stub. | 302 // Jump to stub. |
318 CallApiAccessorStub stub(isolate, is_store, call_data_undefined, | 303 CallApiAccessorStub stub(isolate, is_store, call_data_undefined, |
319 !optimization.is_constant_call()); | 304 !optimization.is_constant_call()); |
320 __ TailCallStub(&stub); | 305 __ TailCallStub(&stub); |
321 } | 306 } |
322 | 307 |
323 | |
324 static void StoreIC_PushArgs(MacroAssembler* masm) { | 308 static void StoreIC_PushArgs(MacroAssembler* masm) { |
325 __ Push(StoreDescriptor::ReceiverRegister(), StoreDescriptor::NameRegister(), | 309 __ Push(StoreDescriptor::ReceiverRegister(), StoreDescriptor::NameRegister(), |
326 StoreDescriptor::ValueRegister(), | 310 StoreDescriptor::ValueRegister(), |
327 VectorStoreICDescriptor::SlotRegister(), | 311 VectorStoreICDescriptor::SlotRegister(), |
328 VectorStoreICDescriptor::VectorRegister()); | 312 VectorStoreICDescriptor::VectorRegister()); |
329 } | 313 } |
330 | 314 |
331 | |
332 void NamedStoreHandlerCompiler::GenerateSlow(MacroAssembler* masm) { | 315 void NamedStoreHandlerCompiler::GenerateSlow(MacroAssembler* masm) { |
333 StoreIC_PushArgs(masm); | 316 StoreIC_PushArgs(masm); |
334 | 317 |
335 // The slow case calls into the runtime to complete the store without causing | 318 // The slow case calls into the runtime to complete the store without causing |
336 // an IC miss that would otherwise cause a transition to the generic stub. | 319 // an IC miss that would otherwise cause a transition to the generic stub. |
337 __ TailCallRuntime(Runtime::kStoreIC_Slow); | 320 __ TailCallRuntime(Runtime::kStoreIC_Slow); |
338 } | 321 } |
339 | 322 |
340 | |
341 void ElementHandlerCompiler::GenerateStoreSlow(MacroAssembler* masm) { | 323 void ElementHandlerCompiler::GenerateStoreSlow(MacroAssembler* masm) { |
342 StoreIC_PushArgs(masm); | 324 StoreIC_PushArgs(masm); |
343 | 325 |
344 // The slow case calls into the runtime to complete the store without causing | 326 // The slow case calls into the runtime to complete the store without causing |
345 // an IC miss that would otherwise cause a transition to the generic stub. | 327 // an IC miss that would otherwise cause a transition to the generic stub. |
346 __ TailCallRuntime(Runtime::kKeyedStoreIC_Slow); | 328 __ TailCallRuntime(Runtime::kKeyedStoreIC_Slow); |
347 } | 329 } |
348 | 330 |
349 | |
350 #undef __ | 331 #undef __ |
351 #define __ ACCESS_MASM(masm()) | 332 #define __ ACCESS_MASM(masm()) |
352 | 333 |
353 | |
354 void NamedStoreHandlerCompiler::GenerateRestoreName(Label* label, | 334 void NamedStoreHandlerCompiler::GenerateRestoreName(Label* label, |
355 Handle<Name> name) { | 335 Handle<Name> name) { |
356 if (!label->is_unused()) { | 336 if (!label->is_unused()) { |
357 __ bind(label); | 337 __ bind(label); |
358 __ mov(this->name(), Operand(name)); | 338 __ mov(this->name(), Operand(name)); |
359 } | 339 } |
360 } | 340 } |
361 | 341 |
362 | |
363 void NamedStoreHandlerCompiler::GenerateRestoreName(Handle<Name> name) { | 342 void NamedStoreHandlerCompiler::GenerateRestoreName(Handle<Name> name) { |
364 __ mov(this->name(), Operand(name)); | 343 __ mov(this->name(), Operand(name)); |
365 } | 344 } |
366 | 345 |
367 | |
368 void NamedStoreHandlerCompiler::RearrangeVectorAndSlot( | 346 void NamedStoreHandlerCompiler::RearrangeVectorAndSlot( |
369 Register current_map, Register destination_map) { | 347 Register current_map, Register destination_map) { |
370 DCHECK(false); // Not implemented. | 348 DCHECK(false); // Not implemented. |
371 } | 349 } |
372 | 350 |
373 | |
374 void NamedStoreHandlerCompiler::GenerateRestoreMap(Handle<Map> transition, | 351 void NamedStoreHandlerCompiler::GenerateRestoreMap(Handle<Map> transition, |
375 Register map_reg, | 352 Register map_reg, |
376 Register scratch, | 353 Register scratch, |
377 Label* miss) { | 354 Label* miss) { |
378 Handle<WeakCell> cell = Map::WeakCellForMap(transition); | 355 Handle<WeakCell> cell = Map::WeakCellForMap(transition); |
379 DCHECK(!map_reg.is(scratch)); | 356 DCHECK(!map_reg.is(scratch)); |
380 __ LoadWeakValue(map_reg, cell, miss); | 357 __ LoadWeakValue(map_reg, cell, miss); |
381 if (transition->CanBeDeprecated()) { | 358 if (transition->CanBeDeprecated()) { |
382 __ lwz(scratch, FieldMemOperand(map_reg, Map::kBitField3Offset)); | 359 __ LoadlW(scratch, FieldMemOperand(map_reg, Map::kBitField3Offset)); |
383 __ DecodeField<Map::Deprecated>(r0, scratch, SetRC); | 360 __ DecodeField<Map::Deprecated>(r0, scratch); |
384 __ bne(miss, cr0); | 361 __ bne(miss); |
385 } | 362 } |
386 } | 363 } |
387 | 364 |
388 | |
389 void NamedStoreHandlerCompiler::GenerateConstantCheck(Register map_reg, | 365 void NamedStoreHandlerCompiler::GenerateConstantCheck(Register map_reg, |
390 int descriptor, | 366 int descriptor, |
391 Register value_reg, | 367 Register value_reg, |
392 Register scratch, | 368 Register scratch, |
393 Label* miss_label) { | 369 Label* miss_label) { |
394 DCHECK(!map_reg.is(scratch)); | 370 DCHECK(!map_reg.is(scratch)); |
395 DCHECK(!map_reg.is(value_reg)); | 371 DCHECK(!map_reg.is(value_reg)); |
396 DCHECK(!value_reg.is(scratch)); | 372 DCHECK(!value_reg.is(scratch)); |
397 __ LoadInstanceDescriptors(map_reg, scratch); | 373 __ LoadInstanceDescriptors(map_reg, scratch); |
398 __ LoadP(scratch, FieldMemOperand( | 374 __ CmpP(value_reg, FieldMemOperand( |
399 scratch, DescriptorArray::GetValueOffset(descriptor))); | 375 scratch, DescriptorArray::GetValueOffset(descriptor))); |
400 __ cmp(value_reg, scratch); | |
401 __ bne(miss_label); | 376 __ bne(miss_label); |
402 } | 377 } |
403 | 378 |
404 void NamedStoreHandlerCompiler::GenerateFieldTypeChecks(FieldType* field_type, | 379 void NamedStoreHandlerCompiler::GenerateFieldTypeChecks(FieldType* field_type, |
405 Register value_reg, | 380 Register value_reg, |
406 Label* miss_label) { | 381 Label* miss_label) { |
407 Register map_reg = scratch1(); | 382 Register map_reg = scratch1(); |
408 Register scratch = scratch2(); | 383 Register scratch = scratch2(); |
409 DCHECK(!value_reg.is(map_reg)); | 384 DCHECK(!value_reg.is(map_reg)); |
410 DCHECK(!value_reg.is(scratch)); | 385 DCHECK(!value_reg.is(scratch)); |
411 __ JumpIfSmi(value_reg, miss_label); | 386 __ JumpIfSmi(value_reg, miss_label); |
412 if (field_type->IsClass()) { | 387 if (field_type->IsClass()) { |
413 __ LoadP(map_reg, FieldMemOperand(value_reg, HeapObject::kMapOffset)); | 388 __ LoadP(map_reg, FieldMemOperand(value_reg, HeapObject::kMapOffset)); |
414 __ CmpWeakValue(map_reg, Map::WeakCellForMap(field_type->AsClass()), | 389 __ CmpWeakValue(map_reg, Map::WeakCellForMap(field_type->AsClass()), |
415 scratch); | 390 scratch); |
416 __ bne(miss_label); | 391 __ bne(miss_label); |
417 } | 392 } |
418 } | 393 } |
419 | 394 |
420 | |
421 Register PropertyHandlerCompiler::CheckPrototypes( | 395 Register PropertyHandlerCompiler::CheckPrototypes( |
422 Register object_reg, Register holder_reg, Register scratch1, | 396 Register object_reg, Register holder_reg, Register scratch1, |
423 Register scratch2, Handle<Name> name, Label* miss, PrototypeCheckType check, | 397 Register scratch2, Handle<Name> name, Label* miss, PrototypeCheckType check, |
424 ReturnHolder return_what) { | 398 ReturnHolder return_what) { |
425 Handle<Map> receiver_map = map(); | 399 Handle<Map> receiver_map = map(); |
426 | 400 |
427 // Make sure there's no overlap between holder and object registers. | 401 // Make sure there's no overlap between holder and object registers. |
428 DCHECK(!scratch1.is(object_reg) && !scratch1.is(holder_reg)); | 402 DCHECK(!scratch1.is(object_reg) && !scratch1.is(holder_reg)); |
429 DCHECK(!scratch2.is(object_reg) && !scratch2.is(holder_reg) && | 403 DCHECK(!scratch2.is(object_reg) && !scratch2.is(holder_reg) && |
430 !scratch2.is(scratch1)); | 404 !scratch2.is(scratch1)); |
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
547 | 521 |
548 bool return_holder = return_what == RETURN_HOLDER; | 522 bool return_holder = return_what == RETURN_HOLDER; |
549 if (FLAG_eliminate_prototype_chain_checks && return_holder && depth != 0) { | 523 if (FLAG_eliminate_prototype_chain_checks && return_holder && depth != 0) { |
550 __ LoadWeakValue(reg, isolate()->factory()->NewWeakCell(current), miss); | 524 __ LoadWeakValue(reg, isolate()->factory()->NewWeakCell(current), miss); |
551 } | 525 } |
552 | 526 |
553 // Return the register containing the holder. | 527 // Return the register containing the holder. |
554 return return_holder ? reg : no_reg; | 528 return return_holder ? reg : no_reg; |
555 } | 529 } |
556 | 530 |
557 | |
558 void NamedLoadHandlerCompiler::FrontendFooter(Handle<Name> name, Label* miss) { | 531 void NamedLoadHandlerCompiler::FrontendFooter(Handle<Name> name, Label* miss) { |
559 if (!miss->is_unused()) { | 532 if (!miss->is_unused()) { |
560 Label success; | 533 Label success; |
561 __ b(&success); | 534 __ b(&success); |
562 __ bind(miss); | 535 __ bind(miss); |
563 if (IC::ICUseVector(kind())) { | 536 if (IC::ICUseVector(kind())) { |
564 DCHECK(kind() == Code::LOAD_IC); | 537 DCHECK(kind() == Code::LOAD_IC); |
565 PopVectorAndSlot(); | 538 PopVectorAndSlot(); |
566 } | 539 } |
567 TailCallBuiltin(masm(), MissBuiltin(kind())); | 540 TailCallBuiltin(masm(), MissBuiltin(kind())); |
568 __ bind(&success); | 541 __ bind(&success); |
569 } | 542 } |
570 } | 543 } |
571 | 544 |
572 | |
573 void NamedStoreHandlerCompiler::FrontendFooter(Handle<Name> name, Label* miss) { | 545 void NamedStoreHandlerCompiler::FrontendFooter(Handle<Name> name, Label* miss) { |
574 if (!miss->is_unused()) { | 546 if (!miss->is_unused()) { |
575 Label success; | 547 Label success; |
576 __ b(&success); | 548 __ b(&success); |
577 GenerateRestoreName(miss, name); | 549 GenerateRestoreName(miss, name); |
578 if (IC::ICUseVector(kind())) PopVectorAndSlot(); | 550 if (IC::ICUseVector(kind())) PopVectorAndSlot(); |
579 TailCallBuiltin(masm(), MissBuiltin(kind())); | 551 TailCallBuiltin(masm(), MissBuiltin(kind())); |
580 __ bind(&success); | 552 __ bind(&success); |
581 } | 553 } |
582 } | 554 } |
583 | 555 |
584 | |
585 void NamedLoadHandlerCompiler::GenerateLoadConstant(Handle<Object> value) { | 556 void NamedLoadHandlerCompiler::GenerateLoadConstant(Handle<Object> value) { |
586 // Return the constant value. | 557 // Return the constant value. |
587 __ Move(r3, value); | 558 __ Move(r2, value); |
588 __ Ret(); | 559 __ Ret(); |
589 } | 560 } |
590 | 561 |
591 | |
592 void NamedLoadHandlerCompiler::GenerateLoadCallback( | 562 void NamedLoadHandlerCompiler::GenerateLoadCallback( |
593 Register reg, Handle<AccessorInfo> callback) { | 563 Register reg, Handle<AccessorInfo> callback) { |
594 DCHECK(!AreAliased(scratch2(), scratch3(), scratch4(), receiver())); | 564 DCHECK(!AreAliased(scratch2(), scratch3(), scratch4(), receiver())); |
595 DCHECK(!AreAliased(scratch2(), scratch3(), scratch4(), reg)); | 565 DCHECK(!AreAliased(scratch2(), scratch3(), scratch4(), reg)); |
596 | 566 |
597 // Build v8::PropertyCallbackInfo::args_ array on the stack and push property | 567 // Build v8::PropertyCallbackInfo::args_ array on the stack and push property |
598 // name below the exit frame to make GC aware of them. | 568 // name below the exit frame to make GC aware of them. |
599 STATIC_ASSERT(PropertyCallbackArguments::kShouldThrowOnErrorIndex == 0); | 569 STATIC_ASSERT(PropertyCallbackArguments::kShouldThrowOnErrorIndex == 0); |
600 STATIC_ASSERT(PropertyCallbackArguments::kHolderIndex == 1); | 570 STATIC_ASSERT(PropertyCallbackArguments::kHolderIndex == 1); |
601 STATIC_ASSERT(PropertyCallbackArguments::kIsolateIndex == 2); | 571 STATIC_ASSERT(PropertyCallbackArguments::kIsolateIndex == 2); |
602 STATIC_ASSERT(PropertyCallbackArguments::kReturnValueDefaultValueIndex == 3); | 572 STATIC_ASSERT(PropertyCallbackArguments::kReturnValueDefaultValueIndex == 3); |
603 STATIC_ASSERT(PropertyCallbackArguments::kReturnValueOffset == 4); | 573 STATIC_ASSERT(PropertyCallbackArguments::kReturnValueOffset == 4); |
604 STATIC_ASSERT(PropertyCallbackArguments::kDataIndex == 5); | 574 STATIC_ASSERT(PropertyCallbackArguments::kDataIndex == 5); |
605 STATIC_ASSERT(PropertyCallbackArguments::kThisIndex == 6); | 575 STATIC_ASSERT(PropertyCallbackArguments::kThisIndex == 6); |
606 STATIC_ASSERT(PropertyCallbackArguments::kArgsLength == 7); | 576 STATIC_ASSERT(PropertyCallbackArguments::kArgsLength == 7); |
607 | 577 |
608 __ push(receiver()); | 578 __ Push(receiver()); |
609 // Push data from AccessorInfo. | 579 // Push data from AccessorInfo. |
610 Handle<Object> data(callback->data(), isolate()); | 580 Handle<Object> data(callback->data(), isolate()); |
611 if (data->IsUndefined() || data->IsSmi()) { | 581 if (data->IsUndefined() || data->IsSmi()) { |
612 __ Move(scratch2(), data); | 582 __ Move(scratch2(), data); |
613 } else { | 583 } else { |
614 Handle<WeakCell> cell = | 584 Handle<WeakCell> cell = |
615 isolate()->factory()->NewWeakCell(Handle<HeapObject>::cast(data)); | 585 isolate()->factory()->NewWeakCell(Handle<HeapObject>::cast(data)); |
616 // The callback is alive if this instruction is executed, | 586 // The callback is alive if this instruction is executed, |
617 // so the weak cell is not cleared and points to data. | 587 // so the weak cell is not cleared and points to data. |
618 __ GetWeakValue(scratch2(), cell); | 588 __ GetWeakValue(scratch2(), cell); |
(...skipping 12 matching lines...) Expand all Loading... |
631 Address getter_address = v8::ToCData<Address>(callback->getter()); | 601 Address getter_address = v8::ToCData<Address>(callback->getter()); |
632 ApiFunction fun(getter_address); | 602 ApiFunction fun(getter_address); |
633 ExternalReference::Type type = ExternalReference::DIRECT_GETTER_CALL; | 603 ExternalReference::Type type = ExternalReference::DIRECT_GETTER_CALL; |
634 ExternalReference ref = ExternalReference(&fun, type, isolate()); | 604 ExternalReference ref = ExternalReference(&fun, type, isolate()); |
635 __ mov(getter_address_reg, Operand(ref)); | 605 __ mov(getter_address_reg, Operand(ref)); |
636 | 606 |
637 CallApiGetterStub stub(isolate()); | 607 CallApiGetterStub stub(isolate()); |
638 __ TailCallStub(&stub); | 608 __ TailCallStub(&stub); |
639 } | 609 } |
640 | 610 |
641 | |
642 void NamedLoadHandlerCompiler::GenerateLoadInterceptorWithFollowup( | 611 void NamedLoadHandlerCompiler::GenerateLoadInterceptorWithFollowup( |
643 LookupIterator* it, Register holder_reg) { | 612 LookupIterator* it, Register holder_reg) { |
644 DCHECK(holder()->HasNamedInterceptor()); | 613 DCHECK(holder()->HasNamedInterceptor()); |
645 DCHECK(!holder()->GetNamedInterceptor()->getter()->IsUndefined()); | 614 DCHECK(!holder()->GetNamedInterceptor()->getter()->IsUndefined()); |
646 | 615 |
647 // Compile the interceptor call, followed by inline code to load the | 616 // Compile the interceptor call, followed by inline code to load the |
648 // property from further up the prototype chain if the call fails. | 617 // property from further up the prototype chain if the call fails. |
649 // Check that the maps haven't changed. | 618 // Check that the maps haven't changed. |
650 DCHECK(holder_reg.is(receiver()) || holder_reg.is(scratch1())); | 619 DCHECK(holder_reg.is(receiver()) || holder_reg.is(scratch1())); |
651 | 620 |
652 // Preserve the receiver register explicitly whenever it is different from the | 621 // Preserve the receiver register explicitly whenever it is different from the |
653 // holder and it is needed should the interceptor return without any result. | 622 // holder and it is needed should the interceptor return without any result. |
654 // The ACCESSOR case needs the receiver to be passed into C++ code, the FIELD | 623 // The ACCESSOR case needs the receiver to be passed into C++ code, the FIELD |
655 // case might cause a miss during the prototype check. | 624 // case might cause a miss during the prototype check. |
656 bool must_perform_prototype_check = | 625 bool must_perform_prototype_check = |
657 !holder().is_identical_to(it->GetHolder<JSObject>()); | 626 !holder().is_identical_to(it->GetHolder<JSObject>()); |
658 bool must_preserve_receiver_reg = | 627 bool must_preserve_receiver_reg = |
659 !receiver().is(holder_reg) && | 628 !receiver().is(holder_reg) && |
660 (it->state() == LookupIterator::ACCESSOR || must_perform_prototype_check); | 629 (it->state() == LookupIterator::ACCESSOR || must_perform_prototype_check); |
661 | 630 |
662 // Save necessary data before invoking an interceptor. | 631 // Save necessary data before invoking an interceptor. |
663 // Requires a frame to make GC aware of pushed pointers. | 632 // Requires a frame to make GC aware of pushed pointers. |
664 { | 633 { |
665 FrameAndConstantPoolScope frame_scope(masm(), StackFrame::INTERNAL); | 634 FrameScope frame_scope(masm(), StackFrame::INTERNAL); |
666 if (must_preserve_receiver_reg) { | 635 if (must_preserve_receiver_reg) { |
667 __ Push(receiver(), holder_reg, this->name()); | 636 __ Push(receiver(), holder_reg, this->name()); |
668 } else { | 637 } else { |
669 __ Push(holder_reg, this->name()); | 638 __ Push(holder_reg, this->name()); |
670 } | 639 } |
671 InterceptorVectorSlotPush(holder_reg); | 640 InterceptorVectorSlotPush(holder_reg); |
672 // Invoke an interceptor. Note: map checks from receiver to | 641 // Invoke an interceptor. Note: map checks from receiver to |
673 // interceptor's holder has been compiled before (see a caller | 642 // interceptor's holder has been compiled before (see a caller |
674 // of this method.) | 643 // of this method.) |
675 CompileCallLoadPropertyWithInterceptor( | 644 CompileCallLoadPropertyWithInterceptor( |
676 masm(), receiver(), holder_reg, this->name(), holder(), | 645 masm(), receiver(), holder_reg, this->name(), holder(), |
677 Runtime::kLoadPropertyWithInterceptorOnly); | 646 Runtime::kLoadPropertyWithInterceptorOnly); |
678 | 647 |
679 // Check if interceptor provided a value for property. If it's | 648 // Check if interceptor provided a value for property. If it's |
680 // the case, return immediately. | 649 // the case, return immediately. |
681 Label interceptor_failed; | 650 Label interceptor_failed; |
682 __ LoadRoot(scratch1(), Heap::kNoInterceptorResultSentinelRootIndex); | 651 __ CompareRoot(r2, Heap::kNoInterceptorResultSentinelRootIndex); |
683 __ cmp(r3, scratch1()); | 652 __ beq(&interceptor_failed, Label::kNear); |
684 __ beq(&interceptor_failed); | |
685 frame_scope.GenerateLeaveFrame(); | 653 frame_scope.GenerateLeaveFrame(); |
686 __ Ret(); | 654 __ Ret(); |
687 | 655 |
688 __ bind(&interceptor_failed); | 656 __ bind(&interceptor_failed); |
689 InterceptorVectorSlotPop(holder_reg); | 657 InterceptorVectorSlotPop(holder_reg); |
690 __ pop(this->name()); | 658 __ Pop(this->name()); |
691 __ pop(holder_reg); | 659 __ Pop(holder_reg); |
692 if (must_preserve_receiver_reg) { | 660 if (must_preserve_receiver_reg) { |
693 __ pop(receiver()); | 661 __ Pop(receiver()); |
694 } | 662 } |
695 // Leave the internal frame. | 663 // Leave the internal frame. |
696 } | 664 } |
697 | 665 |
698 GenerateLoadPostInterceptor(it, holder_reg); | 666 GenerateLoadPostInterceptor(it, holder_reg); |
699 } | 667 } |
700 | 668 |
701 | |
702 void NamedLoadHandlerCompiler::GenerateLoadInterceptor(Register holder_reg) { | 669 void NamedLoadHandlerCompiler::GenerateLoadInterceptor(Register holder_reg) { |
703 // Call the runtime system to load the interceptor. | 670 // Call the runtime system to load the interceptor. |
704 DCHECK(holder()->HasNamedInterceptor()); | 671 DCHECK(holder()->HasNamedInterceptor()); |
705 DCHECK(!holder()->GetNamedInterceptor()->getter()->IsUndefined()); | 672 DCHECK(!holder()->GetNamedInterceptor()->getter()->IsUndefined()); |
706 PushInterceptorArguments(masm(), receiver(), holder_reg, this->name(), | 673 PushInterceptorArguments(masm(), receiver(), holder_reg, this->name(), |
707 holder()); | 674 holder()); |
708 | 675 |
709 __ TailCallRuntime(Runtime::kLoadPropertyWithInterceptor); | 676 __ TailCallRuntime(Runtime::kLoadPropertyWithInterceptor); |
710 } | 677 } |
711 | 678 |
712 | |
713 Handle<Code> NamedStoreHandlerCompiler::CompileStoreCallback( | 679 Handle<Code> NamedStoreHandlerCompiler::CompileStoreCallback( |
714 Handle<JSObject> object, Handle<Name> name, Handle<AccessorInfo> callback, | 680 Handle<JSObject> object, Handle<Name> name, Handle<AccessorInfo> callback, |
715 LanguageMode language_mode) { | 681 LanguageMode language_mode) { |
716 Register holder_reg = Frontend(name); | 682 Register holder_reg = Frontend(name); |
717 | 683 |
718 __ Push(receiver(), holder_reg); // receiver | 684 __ Push(receiver(), holder_reg); // receiver |
719 | 685 |
720 // If the callback cannot leak, then push the callback directly, | 686 // If the callback cannot leak, then push the callback directly, |
721 // otherwise wrap it in a weak cell. | 687 // otherwise wrap it in a weak cell. |
722 if (callback->data()->IsUndefined() || callback->data()->IsSmi()) { | 688 if (callback->data()->IsUndefined() || callback->data()->IsSmi()) { |
723 __ mov(ip, Operand(callback)); | 689 __ mov(ip, Operand(callback)); |
724 } else { | 690 } else { |
725 Handle<WeakCell> cell = isolate()->factory()->NewWeakCell(callback); | 691 Handle<WeakCell> cell = isolate()->factory()->NewWeakCell(callback); |
726 __ mov(ip, Operand(cell)); | 692 __ mov(ip, Operand(cell)); |
727 } | 693 } |
728 __ push(ip); | 694 __ Push(ip); |
729 __ mov(ip, Operand(name)); | 695 __ mov(ip, Operand(name)); |
730 __ Push(ip, value()); | 696 __ Push(ip, value()); |
731 __ Push(Smi::FromInt(language_mode)); | 697 __ Push(Smi::FromInt(language_mode)); |
732 | 698 |
733 // Do tail-call to the runtime system. | 699 // Do tail-call to the runtime system. |
734 __ TailCallRuntime(Runtime::kStoreCallbackProperty); | 700 __ TailCallRuntime(Runtime::kStoreCallbackProperty); |
735 | 701 |
736 // Return the generated code. | 702 // Return the generated code. |
737 return GetCode(kind(), Code::FAST, name); | 703 return GetCode(kind(), Code::FAST, name); |
738 } | 704 } |
739 | 705 |
740 | |
741 Handle<Code> NamedStoreHandlerCompiler::CompileStoreInterceptor( | 706 Handle<Code> NamedStoreHandlerCompiler::CompileStoreInterceptor( |
742 Handle<Name> name) { | 707 Handle<Name> name) { |
743 __ Push(receiver(), this->name(), value()); | 708 __ Push(receiver(), this->name(), value()); |
744 | 709 |
745 // Do tail-call to the runtime system. | 710 // Do tail-call to the runtime system. |
746 __ TailCallRuntime(Runtime::kStorePropertyWithInterceptor); | 711 __ TailCallRuntime(Runtime::kStorePropertyWithInterceptor); |
747 | 712 |
748 // Return the generated code. | 713 // Return the generated code. |
749 return GetCode(kind(), Code::FAST, name); | 714 return GetCode(kind(), Code::FAST, name); |
750 } | 715 } |
751 | 716 |
752 | |
753 Register NamedStoreHandlerCompiler::value() { | 717 Register NamedStoreHandlerCompiler::value() { |
754 return StoreDescriptor::ValueRegister(); | 718 return StoreDescriptor::ValueRegister(); |
755 } | 719 } |
756 | 720 |
757 | |
758 Handle<Code> NamedLoadHandlerCompiler::CompileLoadGlobal( | 721 Handle<Code> NamedLoadHandlerCompiler::CompileLoadGlobal( |
759 Handle<PropertyCell> cell, Handle<Name> name, bool is_configurable) { | 722 Handle<PropertyCell> cell, Handle<Name> name, bool is_configurable) { |
760 Label miss; | 723 Label miss; |
761 if (IC::ICUseVector(kind())) { | 724 if (IC::ICUseVector(kind())) { |
762 PushVectorAndSlot(); | 725 PushVectorAndSlot(); |
763 } | 726 } |
764 FrontendHeader(receiver(), name, &miss, DONT_RETURN_ANYTHING); | 727 FrontendHeader(receiver(), name, &miss, DONT_RETURN_ANYTHING); |
765 | 728 |
766 // Get the value from the cell. | 729 // Get the value from the cell. |
767 Register result = StoreDescriptor::ValueRegister(); | 730 Register result = StoreDescriptor::ValueRegister(); |
768 Handle<WeakCell> weak_cell = factory()->NewWeakCell(cell); | 731 Handle<WeakCell> weak_cell = factory()->NewWeakCell(cell); |
769 __ LoadWeakValue(result, weak_cell, &miss); | 732 __ LoadWeakValue(result, weak_cell, &miss); |
770 __ LoadP(result, FieldMemOperand(result, PropertyCell::kValueOffset)); | 733 __ LoadP(result, FieldMemOperand(result, PropertyCell::kValueOffset)); |
771 | 734 |
772 // Check for deleted property if property can actually be deleted. | 735 // Check for deleted property if property can actually be deleted. |
773 if (is_configurable) { | 736 if (is_configurable) { |
774 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); | 737 __ CompareRoot(result, Heap::kTheHoleValueRootIndex); |
775 __ cmp(result, ip); | |
776 __ beq(&miss); | 738 __ beq(&miss); |
777 } | 739 } |
778 | 740 |
779 Counters* counters = isolate()->counters(); | 741 Counters* counters = isolate()->counters(); |
780 __ IncrementCounter(counters->ic_named_load_global_stub(), 1, r4, r6); | 742 __ IncrementCounter(counters->ic_named_load_global_stub(), 1, r3, r5); |
781 if (IC::ICUseVector(kind())) { | 743 if (IC::ICUseVector(kind())) { |
782 DiscardVectorAndSlot(); | 744 DiscardVectorAndSlot(); |
783 } | 745 } |
784 __ Ret(); | 746 __ Ret(); |
785 | 747 |
786 FrontendFooter(name, &miss); | 748 FrontendFooter(name, &miss); |
787 | 749 |
788 // Return the generated code. | 750 // Return the generated code. |
789 return GetCode(kind(), Code::NORMAL, name); | 751 return GetCode(kind(), Code::NORMAL, name); |
790 } | 752 } |
791 | 753 |
792 | |
793 #undef __ | 754 #undef __ |
794 } // namespace internal | 755 } // namespace internal |
795 } // namespace v8 | 756 } // namespace v8 |
796 | 757 |
797 #endif // V8_TARGET_ARCH_ARM | 758 #endif // V8_TARGET_ARCH_ARM |
OLD | NEW |