| OLD | NEW |
| 1 // Copyright 2014 the V8 project authors. All rights reserved. | 1 // Copyright 2014 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "src/v8.h" | 5 #include "src/v8.h" |
| 6 | 6 |
| 7 #include "src/ic/call-optimization.h" | 7 #include "src/ic/call-optimization.h" |
| 8 #include "src/ic/handler-compiler.h" | 8 #include "src/ic/handler-compiler.h" |
| 9 #include "src/ic/ic.h" | 9 #include "src/ic/ic.h" |
| 10 #include "src/ic/ic-inl.h" | 10 #include "src/ic/ic-inl.h" |
| (...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 122 // Frontend for store uses the name register. It has to be restored before a | 122 // Frontend for store uses the name register. It has to be restored before a |
| 123 // miss. | 123 // miss. |
| 124 Register NamedStoreHandlerCompiler::FrontendHeader(Register object_reg, | 124 Register NamedStoreHandlerCompiler::FrontendHeader(Register object_reg, |
| 125 Handle<Name> name, | 125 Handle<Name> name, |
| 126 Label* miss) { | 126 Label* miss) { |
| 127 return CheckPrototypes(object_reg, this->name(), scratch1(), scratch2(), name, | 127 return CheckPrototypes(object_reg, this->name(), scratch1(), scratch2(), name, |
| 128 miss, SKIP_RECEIVER); | 128 miss, SKIP_RECEIVER); |
| 129 } | 129 } |
| 130 | 130 |
| 131 | 131 |
| 132 Register PropertyHandlerCompiler::Frontend(Register object_reg, | 132 Register PropertyHandlerCompiler::Frontend(Handle<Name> name) { |
| 133 Handle<Name> name) { | |
| 134 Label miss; | 133 Label miss; |
| 135 Register reg = FrontendHeader(object_reg, name, &miss); | 134 if (IC::ICUseVector(kind())) { |
| 135 PushVectorAndSlot(); |
| 136 } |
| 137 Register reg = FrontendHeader(receiver(), name, &miss); |
| 136 FrontendFooter(name, &miss); | 138 FrontendFooter(name, &miss); |
| 139 // The footer consumes the vector and slot from the stack if miss occurs. |
| 140 if (IC::ICUseVector(kind())) { |
| 141 DiscardVectorAndSlot(); |
| 142 } |
| 137 return reg; | 143 return reg; |
| 138 } | 144 } |
| 139 | 145 |
| 140 | 146 |
| 141 void PropertyHandlerCompiler::NonexistentFrontendHeader(Handle<Name> name, | 147 void PropertyHandlerCompiler::NonexistentFrontendHeader(Handle<Name> name, |
| 142 Label* miss, | 148 Label* miss, |
| 143 Register scratch1, | 149 Register scratch1, |
| 144 Register scratch2) { | 150 Register scratch2) { |
| 145 Register holder_reg; | 151 Register holder_reg; |
| 146 Handle<Map> last_map; | 152 Handle<Map> last_map; |
| (...skipping 25 matching lines...) Expand all Loading... |
| 172 NameDictionary::kNotFound); | 178 NameDictionary::kNotFound); |
| 173 GenerateDictionaryNegativeLookup(masm(), miss, holder_reg, name, scratch1, | 179 GenerateDictionaryNegativeLookup(masm(), miss, holder_reg, name, scratch1, |
| 174 scratch2); | 180 scratch2); |
| 175 } | 181 } |
| 176 } | 182 } |
| 177 } | 183 } |
| 178 | 184 |
| 179 | 185 |
| 180 Handle<Code> NamedLoadHandlerCompiler::CompileLoadField(Handle<Name> name, | 186 Handle<Code> NamedLoadHandlerCompiler::CompileLoadField(Handle<Name> name, |
| 181 FieldIndex field) { | 187 FieldIndex field) { |
| 182 Register reg = Frontend(receiver(), name); | 188 Register reg = Frontend(name); |
| 183 __ Move(receiver(), reg); | 189 __ Move(receiver(), reg); |
| 184 LoadFieldStub stub(isolate(), field); | 190 LoadFieldStub stub(isolate(), field); |
| 185 GenerateTailCall(masm(), stub.GetCode()); | 191 GenerateTailCall(masm(), stub.GetCode()); |
| 186 return GetCode(kind(), Code::FAST, name); | 192 return GetCode(kind(), Code::FAST, name); |
| 187 } | 193 } |
| 188 | 194 |
| 189 | 195 |
| 190 Handle<Code> NamedLoadHandlerCompiler::CompileLoadConstant(Handle<Name> name, | 196 Handle<Code> NamedLoadHandlerCompiler::CompileLoadConstant(Handle<Name> name, |
| 191 int constant_index) { | 197 int constant_index) { |
| 192 Register reg = Frontend(receiver(), name); | 198 Register reg = Frontend(name); |
| 193 __ Move(receiver(), reg); | 199 __ Move(receiver(), reg); |
| 194 LoadConstantStub stub(isolate(), constant_index); | 200 LoadConstantStub stub(isolate(), constant_index); |
| 195 GenerateTailCall(masm(), stub.GetCode()); | 201 GenerateTailCall(masm(), stub.GetCode()); |
| 196 return GetCode(kind(), Code::FAST, name); | 202 return GetCode(kind(), Code::FAST, name); |
| 197 } | 203 } |
| 198 | 204 |
| 199 | 205 |
| 200 Handle<Code> NamedLoadHandlerCompiler::CompileLoadNonexistent( | 206 Handle<Code> NamedLoadHandlerCompiler::CompileLoadNonexistent( |
| 201 Handle<Name> name) { | 207 Handle<Name> name) { |
| 202 Label miss; | 208 Label miss; |
| 209 if (IC::ICUseVector(kind())) { |
| 210 DCHECK(kind() == Code::LOAD_IC); |
| 211 PushVectorAndSlot(); |
| 212 } |
| 203 NonexistentFrontendHeader(name, &miss, scratch2(), scratch3()); | 213 NonexistentFrontendHeader(name, &miss, scratch2(), scratch3()); |
| 214 if (IC::ICUseVector(kind())) { |
| 215 DiscardVectorAndSlot(); |
| 216 } |
| 204 GenerateLoadConstant(isolate()->factory()->undefined_value()); | 217 GenerateLoadConstant(isolate()->factory()->undefined_value()); |
| 205 FrontendFooter(name, &miss); | 218 FrontendFooter(name, &miss); |
| 206 return GetCode(kind(), Code::FAST, name); | 219 return GetCode(kind(), Code::FAST, name); |
| 207 } | 220 } |
| 208 | 221 |
| 209 | 222 |
| 210 Handle<Code> NamedLoadHandlerCompiler::CompileLoadCallback( | 223 Handle<Code> NamedLoadHandlerCompiler::CompileLoadCallback( |
| 211 Handle<Name> name, Handle<ExecutableAccessorInfo> callback) { | 224 Handle<Name> name, Handle<ExecutableAccessorInfo> callback) { |
| 212 Register reg = Frontend(receiver(), name); | 225 Register reg = Frontend(name); |
| 213 GenerateLoadCallback(reg, callback); | 226 GenerateLoadCallback(reg, callback); |
| 214 return GetCode(kind(), Code::FAST, name); | 227 return GetCode(kind(), Code::FAST, name); |
| 215 } | 228 } |
| 216 | 229 |
| 217 | 230 |
| 218 Handle<Code> NamedLoadHandlerCompiler::CompileLoadCallback( | 231 Handle<Code> NamedLoadHandlerCompiler::CompileLoadCallback( |
| 219 Handle<Name> name, const CallOptimization& call_optimization) { | 232 Handle<Name> name, const CallOptimization& call_optimization) { |
| 220 DCHECK(call_optimization.is_simple_api_call()); | 233 DCHECK(call_optimization.is_simple_api_call()); |
| 221 Frontend(receiver(), name); | 234 Frontend(name); |
| 222 Handle<Map> receiver_map = IC::TypeToMap(*type(), isolate()); | 235 Handle<Map> receiver_map = IC::TypeToMap(*type(), isolate()); |
| 223 GenerateFastApiCall(masm(), call_optimization, receiver_map, receiver(), | 236 GenerateFastApiCall(masm(), call_optimization, receiver_map, receiver(), |
| 224 scratch1(), false, 0, NULL); | 237 scratch1(), false, 0, NULL); |
| 225 return GetCode(kind(), Code::FAST, name); | 238 return GetCode(kind(), Code::FAST, name); |
| 226 } | 239 } |
| 227 | 240 |
| 228 | 241 |
| 242 void NamedLoadHandlerCompiler::InterceptorVectorSlotPush(Register holder_reg) { |
| 243 if (IC::ICUseVector(kind())) { |
| 244 if (holder_reg.is(receiver())) { |
| 245 PushVectorAndSlot(); |
| 246 } else { |
| 247 DCHECK(holder_reg.is(scratch1())); |
| 248 PushVectorAndSlot(scratch2(), scratch3()); |
| 249 } |
| 250 } |
| 251 } |
| 252 |
| 253 |
| 254 void NamedLoadHandlerCompiler::InterceptorVectorSlotPop(Register holder_reg, |
| 255 PopMode mode) { |
| 256 if (IC::ICUseVector(kind())) { |
| 257 if (mode == DISCARD) { |
| 258 DiscardVectorAndSlot(); |
| 259 } else { |
| 260 if (holder_reg.is(receiver())) { |
| 261 PopVectorAndSlot(); |
| 262 } else { |
| 263 DCHECK(holder_reg.is(scratch1())); |
| 264 PopVectorAndSlot(scratch2(), scratch3()); |
| 265 } |
| 266 } |
| 267 } |
| 268 } |
| 269 |
| 270 |
| 229 Handle<Code> NamedLoadHandlerCompiler::CompileLoadInterceptor( | 271 Handle<Code> NamedLoadHandlerCompiler::CompileLoadInterceptor( |
| 230 LookupIterator* it) { | 272 LookupIterator* it) { |
| 231 // So far the most popular follow ups for interceptor loads are FIELD and | 273 // So far the most popular follow ups for interceptor loads are FIELD and |
| 232 // ExecutableAccessorInfo, so inline only them. Other cases may be added | 274 // ExecutableAccessorInfo, so inline only them. Other cases may be added |
| 233 // later. | 275 // later. |
| 234 bool inline_followup = false; | 276 bool inline_followup = false; |
| 235 switch (it->state()) { | 277 switch (it->state()) { |
| 236 case LookupIterator::TRANSITION: | 278 case LookupIterator::TRANSITION: |
| 237 UNREACHABLE(); | 279 UNREACHABLE(); |
| 238 case LookupIterator::ACCESS_CHECK: | 280 case LookupIterator::ACCESS_CHECK: |
| (...skipping 10 matching lines...) Expand all Loading... |
| 249 inline_followup = accessors->IsExecutableAccessorInfo(); | 291 inline_followup = accessors->IsExecutableAccessorInfo(); |
| 250 if (!inline_followup) break; | 292 if (!inline_followup) break; |
| 251 Handle<ExecutableAccessorInfo> info = | 293 Handle<ExecutableAccessorInfo> info = |
| 252 Handle<ExecutableAccessorInfo>::cast(accessors); | 294 Handle<ExecutableAccessorInfo>::cast(accessors); |
| 253 inline_followup = info->getter() != NULL && | 295 inline_followup = info->getter() != NULL && |
| 254 ExecutableAccessorInfo::IsCompatibleReceiverType( | 296 ExecutableAccessorInfo::IsCompatibleReceiverType( |
| 255 isolate(), info, type()); | 297 isolate(), info, type()); |
| 256 } | 298 } |
| 257 } | 299 } |
| 258 | 300 |
| 259 Register reg = Frontend(receiver(), it->name()); | 301 Label miss; |
| 302 InterceptorVectorSlotPush(receiver()); |
| 303 Register reg = FrontendHeader(receiver(), it->name(), &miss); |
| 304 FrontendFooter(it->name(), &miss); |
| 305 InterceptorVectorSlotPop(reg); |
| 306 |
| 260 if (inline_followup) { | 307 if (inline_followup) { |
| 261 // TODO(368): Compile in the whole chain: all the interceptors in | 308 // TODO(368): Compile in the whole chain: all the interceptors in |
| 262 // prototypes and ultimate answer. | 309 // prototypes and ultimate answer. |
| 263 GenerateLoadInterceptorWithFollowup(it, reg); | 310 GenerateLoadInterceptorWithFollowup(it, reg); |
| 264 } else { | 311 } else { |
| 265 GenerateLoadInterceptor(reg); | 312 GenerateLoadInterceptor(reg); |
| 266 } | 313 } |
| 267 return GetCode(kind(), Code::FAST, it->name()); | 314 return GetCode(kind(), Code::FAST, it->name()); |
| 268 } | 315 } |
| 269 | 316 |
| 270 | 317 |
| 271 void NamedLoadHandlerCompiler::GenerateLoadPostInterceptor( | 318 void NamedLoadHandlerCompiler::GenerateLoadPostInterceptor( |
| 272 LookupIterator* it, Register interceptor_reg) { | 319 LookupIterator* it, Register interceptor_reg) { |
| 273 Handle<JSObject> real_named_property_holder(it->GetHolder<JSObject>()); | 320 Handle<JSObject> real_named_property_holder(it->GetHolder<JSObject>()); |
| 274 | 321 |
| 275 set_type_for_object(holder()); | 322 set_type_for_object(holder()); |
| 276 set_holder(real_named_property_holder); | 323 set_holder(real_named_property_holder); |
| 277 Register reg = Frontend(interceptor_reg, it->name()); | 324 |
| 325 Label miss; |
| 326 InterceptorVectorSlotPush(interceptor_reg); |
| 327 Register reg = FrontendHeader(interceptor_reg, it->name(), &miss); |
| 328 FrontendFooter(it->name(), &miss); |
| 329 // We discard the vector and slot now because we don't miss below this point. |
| 330 InterceptorVectorSlotPop(reg, DISCARD); |
| 278 | 331 |
| 279 switch (it->state()) { | 332 switch (it->state()) { |
| 280 case LookupIterator::ACCESS_CHECK: | 333 case LookupIterator::ACCESS_CHECK: |
| 281 case LookupIterator::INTERCEPTOR: | 334 case LookupIterator::INTERCEPTOR: |
| 282 case LookupIterator::JSPROXY: | 335 case LookupIterator::JSPROXY: |
| 283 case LookupIterator::NOT_FOUND: | 336 case LookupIterator::NOT_FOUND: |
| 284 case LookupIterator::TRANSITION: | 337 case LookupIterator::TRANSITION: |
| 285 UNREACHABLE(); | 338 UNREACHABLE(); |
| 286 case LookupIterator::DATA: { | 339 case LookupIterator::DATA: { |
| 287 DCHECK_EQ(FIELD, it->property_details().type()); | 340 DCHECK_EQ(FIELD, it->property_details().type()); |
| 288 __ Move(receiver(), reg); | 341 __ Move(receiver(), reg); |
| 289 LoadFieldStub stub(isolate(), it->GetFieldIndex()); | 342 LoadFieldStub stub(isolate(), it->GetFieldIndex()); |
| 290 GenerateTailCall(masm(), stub.GetCode()); | 343 GenerateTailCall(masm(), stub.GetCode()); |
| 291 break; | 344 break; |
| 292 } | 345 } |
| 293 case LookupIterator::ACCESSOR: | 346 case LookupIterator::ACCESSOR: |
| 294 Handle<ExecutableAccessorInfo> info = | 347 Handle<ExecutableAccessorInfo> info = |
| 295 Handle<ExecutableAccessorInfo>::cast(it->GetAccessors()); | 348 Handle<ExecutableAccessorInfo>::cast(it->GetAccessors()); |
| 296 DCHECK_NE(NULL, info->getter()); | 349 DCHECK_NE(NULL, info->getter()); |
| 297 GenerateLoadCallback(reg, info); | 350 GenerateLoadCallback(reg, info); |
| 298 } | 351 } |
| 299 } | 352 } |
| 300 | 353 |
| 301 | 354 |
| 302 Handle<Code> NamedLoadHandlerCompiler::CompileLoadViaGetter( | 355 Handle<Code> NamedLoadHandlerCompiler::CompileLoadViaGetter( |
| 303 Handle<Name> name, Handle<JSFunction> getter) { | 356 Handle<Name> name, Handle<JSFunction> getter) { |
| 304 Frontend(receiver(), name); | 357 Frontend(name); |
| 305 GenerateLoadViaGetter(masm(), type(), receiver(), getter); | 358 GenerateLoadViaGetter(masm(), type(), receiver(), getter); |
| 306 return GetCode(kind(), Code::FAST, name); | 359 return GetCode(kind(), Code::FAST, name); |
| 307 } | 360 } |
| 308 | 361 |
| 309 | 362 |
| 310 // TODO(verwaest): Cleanup. holder() is actually the receiver. | 363 // TODO(verwaest): Cleanup. holder() is actually the receiver. |
| 311 Handle<Code> NamedStoreHandlerCompiler::CompileStoreTransition( | 364 Handle<Code> NamedStoreHandlerCompiler::CompileStoreTransition( |
| 312 Handle<Map> transition, Handle<Name> name) { | 365 Handle<Map> transition, Handle<Name> name) { |
| 313 Label miss; | 366 Label miss; |
| 314 | 367 |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 382 GenerateTailCall(masm(), stub.GetCode()); | 435 GenerateTailCall(masm(), stub.GetCode()); |
| 383 | 436 |
| 384 __ bind(&miss); | 437 __ bind(&miss); |
| 385 TailCallBuiltin(masm(), MissBuiltin(kind())); | 438 TailCallBuiltin(masm(), MissBuiltin(kind())); |
| 386 return GetCode(kind(), Code::FAST, it->name()); | 439 return GetCode(kind(), Code::FAST, it->name()); |
| 387 } | 440 } |
| 388 | 441 |
| 389 | 442 |
| 390 Handle<Code> NamedStoreHandlerCompiler::CompileStoreViaSetter( | 443 Handle<Code> NamedStoreHandlerCompiler::CompileStoreViaSetter( |
| 391 Handle<JSObject> object, Handle<Name> name, Handle<JSFunction> setter) { | 444 Handle<JSObject> object, Handle<Name> name, Handle<JSFunction> setter) { |
| 392 Frontend(receiver(), name); | 445 Frontend(name); |
| 393 GenerateStoreViaSetter(masm(), type(), receiver(), setter); | 446 GenerateStoreViaSetter(masm(), type(), receiver(), setter); |
| 394 | 447 |
| 395 return GetCode(kind(), Code::FAST, name); | 448 return GetCode(kind(), Code::FAST, name); |
| 396 } | 449 } |
| 397 | 450 |
| 398 | 451 |
| 399 Handle<Code> NamedStoreHandlerCompiler::CompileStoreCallback( | 452 Handle<Code> NamedStoreHandlerCompiler::CompileStoreCallback( |
| 400 Handle<JSObject> object, Handle<Name> name, | 453 Handle<JSObject> object, Handle<Name> name, |
| 401 const CallOptimization& call_optimization) { | 454 const CallOptimization& call_optimization) { |
| 402 Frontend(receiver(), name); | 455 Frontend(name); |
| 403 Register values[] = {value()}; | 456 Register values[] = {value()}; |
| 404 GenerateFastApiCall(masm(), call_optimization, handle(object->map()), | 457 GenerateFastApiCall(masm(), call_optimization, handle(object->map()), |
| 405 receiver(), scratch1(), true, 1, values); | 458 receiver(), scratch1(), true, 1, values); |
| 406 return GetCode(kind(), Code::FAST, name); | 459 return GetCode(kind(), Code::FAST, name); |
| 407 } | 460 } |
| 408 | 461 |
| 409 | 462 |
| 410 #undef __ | 463 #undef __ |
| 411 | 464 |
| 412 | 465 |
| (...skipping 23 matching lines...) Expand all Loading... |
| 436 DCHECK(elements_kind == DICTIONARY_ELEMENTS); | 489 DCHECK(elements_kind == DICTIONARY_ELEMENTS); |
| 437 cached_stub = LoadDictionaryElementStub(isolate()).GetCode(); | 490 cached_stub = LoadDictionaryElementStub(isolate()).GetCode(); |
| 438 } | 491 } |
| 439 } | 492 } |
| 440 | 493 |
| 441 handlers->Add(cached_stub); | 494 handlers->Add(cached_stub); |
| 442 } | 495 } |
| 443 } | 496 } |
| 444 } | 497 } |
| 445 } // namespace v8::internal | 498 } // namespace v8::internal |
| OLD | NEW |