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 |