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 // Reload lost holder register. | 342 // Reload lost holder register. |
336 auto cell = isolate()->factory()->NewWeakCell(holder()); | 343 auto cell = isolate()->factory()->NewWeakCell(holder()); |
337 __ LoadWeakValue(reg, cell, &miss); | 344 __ LoadWeakValue(reg, cell, &miss); |
338 } | 345 } |
339 FrontendFooter(it->name(), &miss); | 346 FrontendFooter(it->name(), &miss); |
340 InterceptorVectorSlotPop(reg); | 347 InterceptorVectorSlotPop(reg); |
341 if (inline_followup) { | 348 if (inline_followup) { |
(...skipping 10 matching lines...) Expand all Loading... |
352 void NamedLoadHandlerCompiler::GenerateLoadPostInterceptor( | 359 void NamedLoadHandlerCompiler::GenerateLoadPostInterceptor( |
353 LookupIterator* it, Register interceptor_reg) { | 360 LookupIterator* it, Register interceptor_reg) { |
354 Handle<JSObject> real_named_property_holder(it->GetHolder<JSObject>()); | 361 Handle<JSObject> real_named_property_holder(it->GetHolder<JSObject>()); |
355 | 362 |
356 Handle<Map> holder_map(holder()->map()); | 363 Handle<Map> holder_map(holder()->map()); |
357 set_map(holder_map); | 364 set_map(holder_map); |
358 set_holder(real_named_property_holder); | 365 set_holder(real_named_property_holder); |
359 | 366 |
360 Label miss; | 367 Label miss; |
361 InterceptorVectorSlotPush(interceptor_reg); | 368 InterceptorVectorSlotPush(interceptor_reg); |
362 Register reg = FrontendHeader(interceptor_reg, it->name(), &miss); | 369 Register reg = |
| 370 FrontendHeader(interceptor_reg, it->name(), &miss, RETURN_HOLDER); |
363 FrontendFooter(it->name(), &miss); | 371 FrontendFooter(it->name(), &miss); |
364 // We discard the vector and slot now because we don't miss below this point. | 372 // We discard the vector and slot now because we don't miss below this point. |
365 InterceptorVectorSlotPop(reg, DISCARD); | 373 InterceptorVectorSlotPop(reg, DISCARD); |
366 | 374 |
367 switch (it->state()) { | 375 switch (it->state()) { |
368 case LookupIterator::ACCESS_CHECK: | 376 case LookupIterator::ACCESS_CHECK: |
369 case LookupIterator::INTERCEPTOR: | 377 case LookupIterator::INTERCEPTOR: |
370 case LookupIterator::JSPROXY: | 378 case LookupIterator::JSPROXY: |
371 case LookupIterator::NOT_FOUND: | 379 case LookupIterator::NOT_FOUND: |
372 case LookupIterator::INTEGER_INDEXED_EXOTIC: | 380 case LookupIterator::INTEGER_INDEXED_EXOTIC: |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
417 // Find the top object. | 425 // Find the top object. |
418 Handle<JSObject> last; | 426 Handle<JSObject> last; |
419 PrototypeIterator iter(isolate(), holder()); | 427 PrototypeIterator iter(isolate(), holder()); |
420 while (!iter.IsAtEnd()) { | 428 while (!iter.IsAtEnd()) { |
421 last = Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)); | 429 last = Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)); |
422 iter.Advance(); | 430 iter.Advance(); |
423 } | 431 } |
424 if (!last.is_null()) set_holder(last); | 432 if (!last.is_null()) set_holder(last); |
425 NonexistentFrontendHeader(name, &miss, scratch1(), scratch2()); | 433 NonexistentFrontendHeader(name, &miss, scratch1(), scratch2()); |
426 } else { | 434 } else { |
427 FrontendHeader(receiver(), name, &miss); | 435 FrontendHeader(receiver(), name, &miss, DONT_RETURN_ANYTHING); |
428 DCHECK(holder()->HasFastProperties()); | 436 DCHECK(holder()->HasFastProperties()); |
429 } | 437 } |
430 | 438 |
431 int descriptor = transition->LastAdded(); | 439 int descriptor = transition->LastAdded(); |
432 Handle<DescriptorArray> descriptors(transition->instance_descriptors()); | 440 Handle<DescriptorArray> descriptors(transition->instance_descriptors()); |
433 PropertyDetails details = descriptors->GetDetails(descriptor); | 441 PropertyDetails details = descriptors->GetDetails(descriptor); |
434 Representation representation = details.representation(); | 442 Representation representation = details.representation(); |
435 DCHECK(!representation.IsNone()); | 443 DCHECK(!representation.IsNone()); |
436 | 444 |
437 // Stub is never generated for objects that require access checks. | 445 // Stub is never generated for objects that require access checks. |
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
537 DCHECK(elements_kind == DICTIONARY_ELEMENTS); | 545 DCHECK(elements_kind == DICTIONARY_ELEMENTS); |
538 cached_stub = LoadDictionaryElementStub(isolate()).GetCode(); | 546 cached_stub = LoadDictionaryElementStub(isolate()).GetCode(); |
539 } | 547 } |
540 } | 548 } |
541 | 549 |
542 handlers->Add(cached_stub); | 550 handlers->Add(cached_stub); |
543 } | 551 } |
544 } | 552 } |
545 } | 553 } |
546 } // namespace v8::internal | 554 } // namespace v8::internal |
OLD | NEW |