| 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 |