| 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/cpu-profiler.h" | 7 #include "src/cpu-profiler.h" |
| 8 #include "src/ic/call-optimization.h" | 8 #include "src/ic/call-optimization.h" |
| 9 #include "src/ic/handler-compiler.h" | 9 #include "src/ic/handler-compiler.h" |
| 10 #include "src/ic/ic.h" | 10 #include "src/ic/ic.h" |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 80 #endif | 80 #endif |
| 81 return code; | 81 return code; |
| 82 } | 82 } |
| 83 | 83 |
| 84 | 84 |
| 85 #define __ ACCESS_MASM(masm()) | 85 #define __ ACCESS_MASM(masm()) |
| 86 | 86 |
| 87 | 87 |
| 88 Register NamedLoadHandlerCompiler::FrontendHeader(Register object_reg, | 88 Register NamedLoadHandlerCompiler::FrontendHeader(Register object_reg, |
| 89 Handle<Name> name, | 89 Handle<Name> name, |
| 90 Label* miss) { | 90 Label* miss, |
| 91 ReturnHolder return_what) { |
| 91 PrototypeCheckType check_type = CHECK_ALL_MAPS; | 92 PrototypeCheckType check_type = CHECK_ALL_MAPS; |
| 92 int function_index = -1; | 93 int function_index = -1; |
| 93 if (map()->instance_type() < FIRST_NONSTRING_TYPE) { | 94 if (map()->instance_type() < FIRST_NONSTRING_TYPE) { |
| 94 function_index = Context::STRING_FUNCTION_INDEX; | 95 function_index = Context::STRING_FUNCTION_INDEX; |
| 95 } else if (map()->instance_type() == SYMBOL_TYPE) { | 96 } else if (map()->instance_type() == SYMBOL_TYPE) { |
| 96 function_index = Context::SYMBOL_FUNCTION_INDEX; | 97 function_index = Context::SYMBOL_FUNCTION_INDEX; |
| 97 } else if (map()->instance_type() == HEAP_NUMBER_TYPE) { | 98 } else if (map()->instance_type() == HEAP_NUMBER_TYPE) { |
| 98 function_index = Context::NUMBER_FUNCTION_INDEX; | 99 function_index = Context::NUMBER_FUNCTION_INDEX; |
| 99 } else if (*map() == isolate()->heap()->boolean_map()) { | 100 } else if (*map() == isolate()->heap()->boolean_map()) { |
| 100 function_index = Context::BOOLEAN_FUNCTION_INDEX; | 101 function_index = Context::BOOLEAN_FUNCTION_INDEX; |
| 101 } else { | 102 } else { |
| 102 check_type = SKIP_RECEIVER; | 103 check_type = SKIP_RECEIVER; |
| 103 } | 104 } |
| 104 | 105 |
| 105 if (check_type == CHECK_ALL_MAPS) { | 106 if (check_type == CHECK_ALL_MAPS) { |
| 106 GenerateDirectLoadGlobalFunctionPrototype(masm(), function_index, | 107 GenerateDirectLoadGlobalFunctionPrototype(masm(), function_index, |
| 107 scratch1(), miss); | 108 scratch1(), miss); |
| 108 Object* function = isolate()->native_context()->get(function_index); | 109 Object* function = isolate()->native_context()->get(function_index); |
| 109 Object* prototype = JSFunction::cast(function)->instance_prototype(); | 110 Object* prototype = JSFunction::cast(function)->instance_prototype(); |
| 110 Handle<Map> map(JSObject::cast(prototype)->map()); | 111 Handle<Map> map(JSObject::cast(prototype)->map()); |
| 111 set_map(map); | 112 set_map(map); |
| 112 object_reg = scratch1(); | 113 object_reg = scratch1(); |
| 113 } | 114 } |
| 114 | 115 |
| 115 // Check that the maps starting from the prototype haven't changed. | 116 // Check that the maps starting from the prototype haven't changed. |
| 116 return CheckPrototypes(object_reg, scratch1(), scratch2(), scratch3(), name, | 117 return CheckPrototypes(object_reg, scratch1(), scratch2(), scratch3(), name, |
| 117 miss, check_type); | 118 miss, check_type, return_what); |
| 118 } | 119 } |
| 119 | 120 |
| 120 | 121 |
| 121 // 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 |
| 122 // miss. | 123 // miss. |
| 123 Register NamedStoreHandlerCompiler::FrontendHeader(Register object_reg, | 124 Register NamedStoreHandlerCompiler::FrontendHeader(Register object_reg, |
| 124 Handle<Name> name, | 125 Handle<Name> name, |
| 125 Label* miss) { | 126 Label* miss, |
| 127 ReturnHolder return_what) { |
| 126 return CheckPrototypes(object_reg, this->name(), scratch1(), scratch2(), name, | 128 return CheckPrototypes(object_reg, this->name(), scratch1(), scratch2(), name, |
| 127 miss, SKIP_RECEIVER); | 129 miss, SKIP_RECEIVER, return_what); |
| 128 } | 130 } |
| 129 | 131 |
| 130 | 132 |
| 131 Register PropertyHandlerCompiler::Frontend(Handle<Name> name) { | 133 Register PropertyHandlerCompiler::Frontend(Handle<Name> name) { |
| 132 Label miss; | 134 Label miss; |
| 133 if (IC::ICUseVector(kind())) { | 135 if (IC::ICUseVector(kind())) { |
| 134 PushVectorAndSlot(); | 136 PushVectorAndSlot(); |
| 135 } | 137 } |
| 136 Register reg = FrontendHeader(receiver(), name, &miss); | 138 Register reg = FrontendHeader(receiver(), name, &miss, RETURN_HOLDER); |
| 137 FrontendFooter(name, &miss); | 139 FrontendFooter(name, &miss); |
| 138 // The footer consumes the vector and slot from the stack if miss occurs. | 140 // The footer consumes the vector and slot from the stack if miss occurs. |
| 139 if (IC::ICUseVector(kind())) { | 141 if (IC::ICUseVector(kind())) { |
| 140 DiscardVectorAndSlot(); | 142 DiscardVectorAndSlot(); |
| 141 } | 143 } |
| 142 return reg; | 144 return reg; |
| 143 } | 145 } |
| 144 | 146 |
| 145 | 147 |
| 146 void PropertyHandlerCompiler::NonexistentFrontendHeader(Handle<Name> name, | 148 void PropertyHandlerCompiler::NonexistentFrontendHeader(Handle<Name> name, |
| 147 Label* miss, | 149 Label* miss, |
| 148 Register scratch1, | 150 Register scratch1, |
| 149 Register scratch2) { | 151 Register scratch2) { |
| 150 Register holder_reg; | 152 Register holder_reg; |
| 151 Handle<Map> last_map; | 153 Handle<Map> last_map; |
| 152 if (holder().is_null()) { | 154 if (holder().is_null()) { |
| 153 holder_reg = receiver(); | 155 holder_reg = receiver(); |
| 154 last_map = map(); | 156 last_map = map(); |
| 155 // If |type| has null as its prototype, |holder()| is | 157 // If |type| has null as its prototype, |holder()| is |
| 156 // Handle<JSObject>::null(). | 158 // Handle<JSObject>::null(). |
| 157 DCHECK(last_map->prototype() == isolate()->heap()->null_value()); | 159 DCHECK(last_map->prototype() == isolate()->heap()->null_value()); |
| 158 } else { | 160 } else { |
| 159 holder_reg = FrontendHeader(receiver(), name, miss); | |
| 160 last_map = handle(holder()->map()); | 161 last_map = handle(holder()->map()); |
| 162 // This condition matches the branches below. |
| 163 bool need_holder = |
| 164 last_map->is_dictionary_map() && !last_map->IsJSGlobalObjectMap(); |
| 165 holder_reg = |
| 166 FrontendHeader(receiver(), name, miss, |
| 167 need_holder ? RETURN_HOLDER : DONT_RETURN_ANYTHING); |
| 161 } | 168 } |
| 162 | 169 |
| 163 if (last_map->is_dictionary_map()) { | 170 if (last_map->is_dictionary_map()) { |
| 164 if (last_map->IsJSGlobalObjectMap()) { | 171 if (last_map->IsJSGlobalObjectMap()) { |
| 165 Handle<JSGlobalObject> global = | 172 Handle<JSGlobalObject> global = |
| 166 holder().is_null() | 173 holder().is_null() |
| 167 ? Handle<JSGlobalObject>::cast(isolate()->global_object()) | 174 ? Handle<JSGlobalObject>::cast(isolate()->global_object()) |
| 168 : Handle<JSGlobalObject>::cast(holder()); | 175 : Handle<JSGlobalObject>::cast(holder()); |
| 169 GenerateCheckPropertyCell(masm(), global, name, scratch1, miss); | 176 GenerateCheckPropertyCell(masm(), global, name, scratch1, miss); |
| 170 } else { | 177 } else { |
| (...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 321 JSObject* last = *holder(); | 328 JSObject* last = *holder(); |
| 322 PrototypeIterator iter(isolate(), last); | 329 PrototypeIterator iter(isolate(), last); |
| 323 while (!iter.IsAtEnd()) { | 330 while (!iter.IsAtEnd()) { |
| 324 lost_holder_register = true; | 331 lost_holder_register = true; |
| 325 last = JSObject::cast(iter.GetCurrent()); | 332 last = JSObject::cast(iter.GetCurrent()); |
| 326 iter.Advance(); | 333 iter.Advance(); |
| 327 } | 334 } |
| 328 auto last_handle = handle(last); | 335 auto last_handle = handle(last); |
| 329 set_holder(last_handle); | 336 set_holder(last_handle); |
| 330 } | 337 } |
| 331 Register reg = FrontendHeader(receiver(), it->name(), &miss); | 338 Register reg = FrontendHeader(receiver(), it->name(), &miss, RETURN_HOLDER); |
| 332 // Reset the holder so further calculations are correct. | 339 // Reset the holder so further calculations are correct. |
| 333 set_holder(holder_orig); | 340 set_holder(holder_orig); |
| 334 if (lost_holder_register) { | 341 if (lost_holder_register) { |
| 335 if (*it->GetReceiver() == *holder()) { | 342 if (*it->GetReceiver() == *holder()) { |
| 336 reg = receiver(); | 343 reg = receiver(); |
| 337 } else { | 344 } else { |
| 338 // Reload lost holder register. | 345 // Reload lost holder register. |
| 339 auto cell = isolate()->factory()->NewWeakCell(holder()); | 346 auto cell = isolate()->factory()->NewWeakCell(holder()); |
| 340 __ LoadWeakValue(reg, cell, &miss); | 347 __ LoadWeakValue(reg, cell, &miss); |
| 341 } | 348 } |
| (...skipping 14 matching lines...) Expand all Loading... |
| 356 void NamedLoadHandlerCompiler::GenerateLoadPostInterceptor( | 363 void NamedLoadHandlerCompiler::GenerateLoadPostInterceptor( |
| 357 LookupIterator* it, Register interceptor_reg) { | 364 LookupIterator* it, Register interceptor_reg) { |
| 358 Handle<JSObject> real_named_property_holder(it->GetHolder<JSObject>()); | 365 Handle<JSObject> real_named_property_holder(it->GetHolder<JSObject>()); |
| 359 | 366 |
| 360 Handle<Map> holder_map(holder()->map()); | 367 Handle<Map> holder_map(holder()->map()); |
| 361 set_map(holder_map); | 368 set_map(holder_map); |
| 362 set_holder(real_named_property_holder); | 369 set_holder(real_named_property_holder); |
| 363 | 370 |
| 364 Label miss; | 371 Label miss; |
| 365 InterceptorVectorSlotPush(interceptor_reg); | 372 InterceptorVectorSlotPush(interceptor_reg); |
| 366 Register reg = FrontendHeader(interceptor_reg, it->name(), &miss); | 373 Register reg = |
| 374 FrontendHeader(interceptor_reg, it->name(), &miss, RETURN_HOLDER); |
| 367 FrontendFooter(it->name(), &miss); | 375 FrontendFooter(it->name(), &miss); |
| 368 // We discard the vector and slot now because we don't miss below this point. | 376 // We discard the vector and slot now because we don't miss below this point. |
| 369 InterceptorVectorSlotPop(reg, DISCARD); | 377 InterceptorVectorSlotPop(reg, DISCARD); |
| 370 | 378 |
| 371 switch (it->state()) { | 379 switch (it->state()) { |
| 372 case LookupIterator::ACCESS_CHECK: | 380 case LookupIterator::ACCESS_CHECK: |
| 373 case LookupIterator::INTERCEPTOR: | 381 case LookupIterator::INTERCEPTOR: |
| 374 case LookupIterator::JSPROXY: | 382 case LookupIterator::JSPROXY: |
| 375 case LookupIterator::NOT_FOUND: | 383 case LookupIterator::NOT_FOUND: |
| 376 case LookupIterator::INTEGER_INDEXED_EXOTIC: | 384 case LookupIterator::INTEGER_INDEXED_EXOTIC: |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 421 // Find the top object. | 429 // Find the top object. |
| 422 Handle<JSObject> last; | 430 Handle<JSObject> last; |
| 423 PrototypeIterator iter(isolate(), holder()); | 431 PrototypeIterator iter(isolate(), holder()); |
| 424 while (!iter.IsAtEnd()) { | 432 while (!iter.IsAtEnd()) { |
| 425 last = Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)); | 433 last = Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)); |
| 426 iter.Advance(); | 434 iter.Advance(); |
| 427 } | 435 } |
| 428 if (!last.is_null()) set_holder(last); | 436 if (!last.is_null()) set_holder(last); |
| 429 NonexistentFrontendHeader(name, &miss, scratch1(), scratch2()); | 437 NonexistentFrontendHeader(name, &miss, scratch1(), scratch2()); |
| 430 } else { | 438 } else { |
| 431 FrontendHeader(receiver(), name, &miss); | 439 FrontendHeader(receiver(), name, &miss, DONT_RETURN_ANYTHING); |
| 432 DCHECK(holder()->HasFastProperties()); | 440 DCHECK(holder()->HasFastProperties()); |
| 433 } | 441 } |
| 434 | 442 |
| 435 int descriptor = transition->LastAdded(); | 443 int descriptor = transition->LastAdded(); |
| 436 Handle<DescriptorArray> descriptors(transition->instance_descriptors()); | 444 Handle<DescriptorArray> descriptors(transition->instance_descriptors()); |
| 437 PropertyDetails details = descriptors->GetDetails(descriptor); | 445 PropertyDetails details = descriptors->GetDetails(descriptor); |
| 438 Representation representation = details.representation(); | 446 Representation representation = details.representation(); |
| 439 DCHECK(!representation.IsNone()); | 447 DCHECK(!representation.IsNone()); |
| 440 | 448 |
| 441 // Stub is never generated for objects that require access checks. | 449 // Stub is never generated for objects that require access checks. |
| (...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 541 DCHECK(elements_kind == DICTIONARY_ELEMENTS); | 549 DCHECK(elements_kind == DICTIONARY_ELEMENTS); |
| 542 cached_stub = LoadDictionaryElementStub(isolate()).GetCode(); | 550 cached_stub = LoadDictionaryElementStub(isolate()).GetCode(); |
| 543 } | 551 } |
| 544 } | 552 } |
| 545 | 553 |
| 546 handlers->Add(cached_stub); | 554 handlers->Add(cached_stub); |
| 547 } | 555 } |
| 548 } | 556 } |
| 549 } | 557 } |
| 550 } // namespace v8::internal | 558 } // namespace v8::internal |
| OLD | NEW |