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

Side by Side Diff: src/ic/mips64/handler-compiler-mips64.cc

Issue 2829073002: MIPS64: Move load/store instructions to macro-assembler. (Closed)
Patch Set: Created 3 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/full-codegen/mips64/full-codegen-mips64.cc ('k') | src/mips64/assembler-mips64.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 #if V8_TARGET_ARCH_MIPS64 5 #if V8_TARGET_ARCH_MIPS64
6 6
7 #include "src/ic/handler-compiler.h" 7 #include "src/ic/handler-compiler.h"
8 8
9 #include "src/api-arguments.h" 9 #include "src/api-arguments.h"
10 #include "src/field-type.h" 10 #include "src/field-type.h"
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
43 // Save context and value registers, so we can restore them later. 43 // Save context and value registers, so we can restore them later.
44 __ Push(cp, value()); 44 __ Push(cp, value());
45 45
46 if (accessor_index >= 0) { 46 if (accessor_index >= 0) {
47 DCHECK(!holder.is(scratch)); 47 DCHECK(!holder.is(scratch));
48 DCHECK(!receiver.is(scratch)); 48 DCHECK(!receiver.is(scratch));
49 DCHECK(!value().is(scratch)); 49 DCHECK(!value().is(scratch));
50 // Call the JavaScript setter with receiver and value on the stack. 50 // Call the JavaScript setter with receiver and value on the stack.
51 if (map->IsJSGlobalObjectMap()) { 51 if (map->IsJSGlobalObjectMap()) {
52 // Swap in the global receiver. 52 // Swap in the global receiver.
53 __ ld(scratch, 53 __ Ld(scratch,
54 FieldMemOperand(receiver, JSGlobalObject::kGlobalProxyOffset)); 54 FieldMemOperand(receiver, JSGlobalObject::kGlobalProxyOffset));
55 receiver = scratch; 55 receiver = scratch;
56 } 56 }
57 __ Push(receiver, value()); 57 __ Push(receiver, value());
58 __ LoadAccessor(a1, holder, accessor_index, ACCESSOR_SETTER); 58 __ LoadAccessor(a1, holder, accessor_index, ACCESSOR_SETTER);
59 __ li(a0, Operand(1)); 59 __ li(a0, Operand(1));
60 __ Call(masm->isolate()->builtins()->CallFunction( 60 __ Call(masm->isolate()->builtins()->CallFunction(
61 ConvertReceiverMode::kNotNullOrUndefined), 61 ConvertReceiverMode::kNotNullOrUndefined),
62 RelocInfo::CODE_TARGET); 62 RelocInfo::CODE_TARGET);
63 } else { 63 } else {
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
108 __ IncrementCounter(counters->negative_lookups(), 1, scratch0, scratch1); 108 __ IncrementCounter(counters->negative_lookups(), 1, scratch0, scratch1);
109 __ IncrementCounter(counters->negative_lookups_miss(), 1, scratch0, scratch1); 109 __ IncrementCounter(counters->negative_lookups_miss(), 1, scratch0, scratch1);
110 110
111 Label done; 111 Label done;
112 112
113 const int kInterceptorOrAccessCheckNeededMask = 113 const int kInterceptorOrAccessCheckNeededMask =
114 (1 << Map::kHasNamedInterceptor) | (1 << Map::kIsAccessCheckNeeded); 114 (1 << Map::kHasNamedInterceptor) | (1 << Map::kIsAccessCheckNeeded);
115 115
116 // Bail out if the receiver has a named interceptor or requires access checks. 116 // Bail out if the receiver has a named interceptor or requires access checks.
117 Register map = scratch1; 117 Register map = scratch1;
118 __ ld(map, FieldMemOperand(receiver, HeapObject::kMapOffset)); 118 __ Ld(map, FieldMemOperand(receiver, HeapObject::kMapOffset));
119 __ lbu(scratch0, FieldMemOperand(map, Map::kBitFieldOffset)); 119 __ Lbu(scratch0, FieldMemOperand(map, Map::kBitFieldOffset));
120 __ And(scratch0, scratch0, Operand(kInterceptorOrAccessCheckNeededMask)); 120 __ And(scratch0, scratch0, Operand(kInterceptorOrAccessCheckNeededMask));
121 __ Branch(miss_label, ne, scratch0, Operand(zero_reg)); 121 __ Branch(miss_label, ne, scratch0, Operand(zero_reg));
122 122
123 // Check that receiver is a JSObject. 123 // Check that receiver is a JSObject.
124 __ lbu(scratch0, FieldMemOperand(map, Map::kInstanceTypeOffset)); 124 __ Lbu(scratch0, FieldMemOperand(map, Map::kInstanceTypeOffset));
125 __ Branch(miss_label, lt, scratch0, Operand(FIRST_JS_RECEIVER_TYPE)); 125 __ Branch(miss_label, lt, scratch0, Operand(FIRST_JS_RECEIVER_TYPE));
126 126
127 // Load properties array. 127 // Load properties array.
128 Register properties = scratch0; 128 Register properties = scratch0;
129 __ ld(properties, FieldMemOperand(receiver, JSObject::kPropertiesOffset)); 129 __ Ld(properties, FieldMemOperand(receiver, JSObject::kPropertiesOffset));
130 // Check that the properties array is a dictionary. 130 // Check that the properties array is a dictionary.
131 __ ld(map, FieldMemOperand(properties, HeapObject::kMapOffset)); 131 __ Ld(map, FieldMemOperand(properties, HeapObject::kMapOffset));
132 Register tmp = properties; 132 Register tmp = properties;
133 __ LoadRoot(tmp, Heap::kHashTableMapRootIndex); 133 __ LoadRoot(tmp, Heap::kHashTableMapRootIndex);
134 __ Branch(miss_label, ne, map, Operand(tmp)); 134 __ Branch(miss_label, ne, map, Operand(tmp));
135 135
136 // Restore the temporarily used register. 136 // Restore the temporarily used register.
137 __ ld(properties, FieldMemOperand(receiver, JSObject::kPropertiesOffset)); 137 __ Ld(properties, FieldMemOperand(receiver, JSObject::kPropertiesOffset));
138
139 138
140 NameDictionaryLookupStub::GenerateNegativeLookup( 139 NameDictionaryLookupStub::GenerateNegativeLookup(
141 masm, miss_label, &done, receiver, properties, name, scratch1); 140 masm, miss_label, &done, receiver, properties, name, scratch1);
142 __ bind(&done); 141 __ bind(&done);
143 __ DecrementCounter(counters->negative_lookups_miss(), 1, scratch0, scratch1); 142 __ DecrementCounter(counters->negative_lookups_miss(), 1, scratch0, scratch1);
144 } 143 }
145 144
146 // Generate code to check that a global property cell is empty. Create 145 // Generate code to check that a global property cell is empty. Create
147 // the property cell at compilation time if no cell exists for the 146 // the property cell at compilation time if no cell exists for the
148 // property. 147 // property.
149 void PropertyHandlerCompiler::GenerateCheckPropertyCell( 148 void PropertyHandlerCompiler::GenerateCheckPropertyCell(
150 MacroAssembler* masm, Handle<JSGlobalObject> global, Handle<Name> name, 149 MacroAssembler* masm, Handle<JSGlobalObject> global, Handle<Name> name,
151 Register scratch, Label* miss) { 150 Register scratch, Label* miss) {
152 Handle<PropertyCell> cell = JSGlobalObject::EnsureEmptyPropertyCell( 151 Handle<PropertyCell> cell = JSGlobalObject::EnsureEmptyPropertyCell(
153 global, name, PropertyCellType::kInvalidated); 152 global, name, PropertyCellType::kInvalidated);
154 Isolate* isolate = masm->isolate(); 153 Isolate* isolate = masm->isolate();
155 DCHECK(cell->value()->IsTheHole(isolate)); 154 DCHECK(cell->value()->IsTheHole(isolate));
156 Handle<WeakCell> weak_cell = isolate->factory()->NewWeakCell(cell); 155 Handle<WeakCell> weak_cell = isolate->factory()->NewWeakCell(cell);
157 __ LoadWeakValue(scratch, weak_cell, miss); 156 __ LoadWeakValue(scratch, weak_cell, miss);
158 __ ld(scratch, FieldMemOperand(scratch, PropertyCell::kValueOffset)); 157 __ Ld(scratch, FieldMemOperand(scratch, PropertyCell::kValueOffset));
159 __ LoadRoot(at, Heap::kTheHoleValueRootIndex); 158 __ LoadRoot(at, Heap::kTheHoleValueRootIndex);
160 __ Branch(miss, ne, scratch, Operand(at)); 159 __ Branch(miss, ne, scratch, Operand(at));
161 } 160 }
162 161
163 // Generate call to api function. 162 // Generate call to api function.
164 void PropertyHandlerCompiler::GenerateApiAccessorCall( 163 void PropertyHandlerCompiler::GenerateApiAccessorCall(
165 MacroAssembler* masm, const CallOptimization& optimization, 164 MacroAssembler* masm, const CallOptimization& optimization,
166 Handle<Map> receiver_map, Register receiver, Register scratch_in, 165 Handle<Map> receiver_map, Register receiver, Register scratch_in,
167 bool is_store, Register store_parameter, Register accessor_holder, 166 bool is_store, Register store_parameter, Register accessor_holder,
168 int accessor_index) { 167 int accessor_index) {
(...skipping 21 matching lines...) Expand all
190 // Put holder in place. 189 // Put holder in place.
191 CallOptimization::HolderLookup holder_lookup; 190 CallOptimization::HolderLookup holder_lookup;
192 int holder_depth = 0; 191 int holder_depth = 0;
193 optimization.LookupHolderOfExpectedType(receiver_map, &holder_lookup, 192 optimization.LookupHolderOfExpectedType(receiver_map, &holder_lookup,
194 &holder_depth); 193 &holder_depth);
195 switch (holder_lookup) { 194 switch (holder_lookup) {
196 case CallOptimization::kHolderIsReceiver: 195 case CallOptimization::kHolderIsReceiver:
197 __ Move(holder, receiver); 196 __ Move(holder, receiver);
198 break; 197 break;
199 case CallOptimization::kHolderFound: 198 case CallOptimization::kHolderFound:
200 __ ld(holder, FieldMemOperand(receiver, HeapObject::kMapOffset)); 199 __ Ld(holder, FieldMemOperand(receiver, HeapObject::kMapOffset));
201 __ ld(holder, FieldMemOperand(holder, Map::kPrototypeOffset)); 200 __ Ld(holder, FieldMemOperand(holder, Map::kPrototypeOffset));
202 for (int i = 1; i < holder_depth; i++) { 201 for (int i = 1; i < holder_depth; i++) {
203 __ ld(holder, FieldMemOperand(holder, HeapObject::kMapOffset)); 202 __ Ld(holder, FieldMemOperand(holder, HeapObject::kMapOffset));
204 __ ld(holder, FieldMemOperand(holder, Map::kPrototypeOffset)); 203 __ Ld(holder, FieldMemOperand(holder, Map::kPrototypeOffset));
205 } 204 }
206 break; 205 break;
207 case CallOptimization::kHolderNotFound: 206 case CallOptimization::kHolderNotFound:
208 UNREACHABLE(); 207 UNREACHABLE();
209 break; 208 break;
210 } 209 }
211 210
212 Isolate* isolate = masm->isolate(); 211 Isolate* isolate = masm->isolate();
213 Handle<CallHandlerInfo> api_call_info = optimization.api_call_info(); 212 Handle<CallHandlerInfo> api_call_info = optimization.api_call_info();
214 bool call_data_undefined = false; 213 bool call_data_undefined = false;
215 // Put call data in place. 214 // Put call data in place.
216 if (api_call_info->data()->IsUndefined(isolate)) { 215 if (api_call_info->data()->IsUndefined(isolate)) {
217 call_data_undefined = true; 216 call_data_undefined = true;
218 __ LoadRoot(data, Heap::kUndefinedValueRootIndex); 217 __ LoadRoot(data, Heap::kUndefinedValueRootIndex);
219 } else { 218 } else {
220 if (optimization.is_constant_call()) { 219 if (optimization.is_constant_call()) {
221 __ ld(data, 220 __ Ld(data,
222 FieldMemOperand(callee, JSFunction::kSharedFunctionInfoOffset)); 221 FieldMemOperand(callee, JSFunction::kSharedFunctionInfoOffset));
223 __ ld(data, 222 __ Ld(data,
224 FieldMemOperand(data, SharedFunctionInfo::kFunctionDataOffset)); 223 FieldMemOperand(data, SharedFunctionInfo::kFunctionDataOffset));
225 __ ld(data, FieldMemOperand(data, FunctionTemplateInfo::kCallCodeOffset)); 224 __ Ld(data, FieldMemOperand(data, FunctionTemplateInfo::kCallCodeOffset));
226 } else { 225 } else {
227 __ ld(data, 226 __ Ld(data,
228 FieldMemOperand(callee, FunctionTemplateInfo::kCallCodeOffset)); 227 FieldMemOperand(callee, FunctionTemplateInfo::kCallCodeOffset));
229 } 228 }
230 __ ld(data, FieldMemOperand(data, CallHandlerInfo::kDataOffset)); 229 __ Ld(data, FieldMemOperand(data, CallHandlerInfo::kDataOffset));
231 } 230 }
232 231
233 // Put api_function_address in place. 232 // Put api_function_address in place.
234 Address function_address = v8::ToCData<Address>(api_call_info->callback()); 233 Address function_address = v8::ToCData<Address>(api_call_info->callback());
235 ApiFunction fun(function_address); 234 ApiFunction fun(function_address);
236 ExternalReference::Type type = ExternalReference::DIRECT_API_CALL; 235 ExternalReference::Type type = ExternalReference::DIRECT_API_CALL;
237 ExternalReference ref = ExternalReference(&fun, type, masm->isolate()); 236 ExternalReference ref = ExternalReference(&fun, type, masm->isolate());
238 __ li(api_function_address, Operand(ref)); 237 __ li(api_function_address, Operand(ref));
239 238
240 // Jump to stub. 239 // Jump to stub.
(...skipping 12 matching lines...) Expand all
253 __ bind(label); 252 __ bind(label);
254 __ li(this->name(), Operand(name)); 253 __ li(this->name(), Operand(name));
255 } 254 }
256 } 255 }
257 256
258 void PropertyHandlerCompiler::GenerateAccessCheck( 257 void PropertyHandlerCompiler::GenerateAccessCheck(
259 Handle<WeakCell> native_context_cell, Register scratch1, Register scratch2, 258 Handle<WeakCell> native_context_cell, Register scratch1, Register scratch2,
260 Label* miss, bool compare_native_contexts_only) { 259 Label* miss, bool compare_native_contexts_only) {
261 Label done; 260 Label done;
262 // Load current native context. 261 // Load current native context.
263 __ ld(scratch1, NativeContextMemOperand()); 262 __ Ld(scratch1, NativeContextMemOperand());
264 // Load expected native context. 263 // Load expected native context.
265 __ LoadWeakValue(scratch2, native_context_cell, miss); 264 __ LoadWeakValue(scratch2, native_context_cell, miss);
266 265
267 if (!compare_native_contexts_only) { 266 if (!compare_native_contexts_only) {
268 __ Branch(&done, eq, scratch1, Operand(scratch2)); 267 __ Branch(&done, eq, scratch1, Operand(scratch2));
269 268
270 // Compare security tokens of current and expected native contexts. 269 // Compare security tokens of current and expected native contexts.
271 __ ld(scratch1, ContextMemOperand(scratch1, Context::SECURITY_TOKEN_INDEX)); 270 __ Ld(scratch1, ContextMemOperand(scratch1, Context::SECURITY_TOKEN_INDEX));
272 __ ld(scratch2, ContextMemOperand(scratch2, Context::SECURITY_TOKEN_INDEX)); 271 __ Ld(scratch2, ContextMemOperand(scratch2, Context::SECURITY_TOKEN_INDEX));
273 } 272 }
274 __ Branch(miss, ne, scratch1, Operand(scratch2)); 273 __ Branch(miss, ne, scratch1, Operand(scratch2));
275 274
276 __ bind(&done); 275 __ bind(&done);
277 } 276 }
278 277
279 Register PropertyHandlerCompiler::CheckPrototypes( 278 Register PropertyHandlerCompiler::CheckPrototypes(
280 Register object_reg, Register holder_reg, Register scratch1, 279 Register object_reg, Register holder_reg, Register scratch1,
281 Register scratch2, Handle<Name> name, Label* miss) { 280 Register scratch2, Handle<Name> name, Label* miss) {
282 Handle<Map> receiver_map = map(); 281 Handle<Map> receiver_map = map();
283 282
284 // Make sure there's no overlap between holder and object registers. 283 // Make sure there's no overlap between holder and object registers.
285 DCHECK(!scratch1.is(object_reg) && !scratch1.is(holder_reg)); 284 DCHECK(!scratch1.is(object_reg) && !scratch1.is(holder_reg));
286 DCHECK(!scratch2.is(object_reg) && !scratch2.is(holder_reg) && 285 DCHECK(!scratch2.is(object_reg) && !scratch2.is(holder_reg) &&
287 !scratch2.is(scratch1)); 286 !scratch2.is(scratch1));
288 287
289 Handle<Cell> validity_cell = 288 Handle<Cell> validity_cell =
290 Map::GetOrCreatePrototypeChainValidityCell(receiver_map, isolate()); 289 Map::GetOrCreatePrototypeChainValidityCell(receiver_map, isolate());
291 if (!validity_cell.is_null()) { 290 if (!validity_cell.is_null()) {
292 DCHECK_EQ(Smi::FromInt(Map::kPrototypeChainValid), validity_cell->value()); 291 DCHECK_EQ(Smi::FromInt(Map::kPrototypeChainValid), validity_cell->value());
293 __ li(scratch1, Operand(validity_cell)); 292 __ li(scratch1, Operand(validity_cell));
294 __ ld(scratch1, FieldMemOperand(scratch1, Cell::kValueOffset)); 293 __ Ld(scratch1, FieldMemOperand(scratch1, Cell::kValueOffset));
295 __ Branch(miss, ne, scratch1, 294 __ Branch(miss, ne, scratch1,
296 Operand(Smi::FromInt(Map::kPrototypeChainValid))); 295 Operand(Smi::FromInt(Map::kPrototypeChainValid)));
297 } 296 }
298 297
299 // Keep track of the current object in register reg. 298 // Keep track of the current object in register reg.
300 Register reg = object_reg; 299 Register reg = object_reg;
301 int depth = 0; 300 int depth = 0;
302 301
303 Handle<JSObject> current = Handle<JSObject>::null(); 302 Handle<JSObject> current = Handle<JSObject>::null();
304 if (receiver_map->IsJSGlobalObjectMap()) { 303 if (receiver_map->IsJSGlobalObjectMap()) {
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after
412 Register NamedStoreHandlerCompiler::value() { 411 Register NamedStoreHandlerCompiler::value() {
413 return StoreDescriptor::ValueRegister(); 412 return StoreDescriptor::ValueRegister();
414 } 413 }
415 414
416 415
417 #undef __ 416 #undef __
418 } // namespace internal 417 } // namespace internal
419 } // namespace v8 418 } // namespace v8
420 419
421 #endif // V8_TARGET_ARCH_MIPS64 420 #endif // V8_TARGET_ARCH_MIPS64
OLDNEW
« no previous file with comments | « src/full-codegen/mips64/full-codegen-mips64.cc ('k') | src/mips64/assembler-mips64.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698