Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2016 the V8 project authors. All rights reserved. | 1 // Copyright 2016 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/ic/accessor-assembler.h" | 5 #include "src/ic/accessor-assembler.h" |
| 6 | 6 |
| 7 #include "src/code-factory.h" | 7 #include "src/code-factory.h" |
| 8 #include "src/code-stubs.h" | 8 #include "src/code-stubs.h" |
| 9 #include "src/ic/handler-configuration.h" | 9 #include "src/ic/handler-configuration.h" |
| 10 #include "src/ic/stub-cache.h" | 10 #include "src/ic/stub-cache.h" |
| (...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 134 }, | 134 }, |
| 135 kEntrySize, INTPTR_PARAMETERS, IndexAdvanceMode::kPost); | 135 kEntrySize, INTPTR_PARAMETERS, IndexAdvanceMode::kPost); |
| 136 // The loop falls through if no handler was found. | 136 // The loop falls through if no handler was found. |
| 137 Goto(if_miss); | 137 Goto(if_miss); |
| 138 } | 138 } |
| 139 | 139 |
| 140 void AccessorAssembler::HandleLoadICHandlerCase( | 140 void AccessorAssembler::HandleLoadICHandlerCase( |
| 141 const LoadICParameters* p, Node* handler, Label* miss, | 141 const LoadICParameters* p, Node* handler, Label* miss, |
| 142 ElementSupport support_elements) { | 142 ElementSupport support_elements) { |
| 143 Comment("have_handler"); | 143 Comment("have_handler"); |
| 144 ExitPoint direct_exit(this); | |
| 145 | |
| 144 Variable var_holder(this, MachineRepresentation::kTagged); | 146 Variable var_holder(this, MachineRepresentation::kTagged); |
| 145 var_holder.Bind(p->receiver); | 147 var_holder.Bind(p->receiver); |
| 146 Variable var_smi_handler(this, MachineRepresentation::kTagged); | 148 Variable var_smi_handler(this, MachineRepresentation::kTagged); |
| 147 var_smi_handler.Bind(handler); | 149 var_smi_handler.Bind(handler); |
| 148 | 150 |
| 149 Variable* vars[] = {&var_holder, &var_smi_handler}; | 151 Variable* vars[] = {&var_holder, &var_smi_handler}; |
| 150 Label if_smi_handler(this, 2, vars); | 152 Label if_smi_handler(this, 2, vars); |
| 151 Label try_proto_handler(this), call_handler(this); | 153 Label try_proto_handler(this), call_handler(this); |
| 152 | 154 |
| 153 Branch(TaggedIsSmi(handler), &if_smi_handler, &try_proto_handler); | 155 Branch(TaggedIsSmi(handler), &if_smi_handler, &try_proto_handler); |
| 154 | 156 |
| 155 // |handler| is a Smi, encoding what to do. See SmiHandler methods | 157 // |handler| is a Smi, encoding what to do. See SmiHandler methods |
| 156 // for the encoding format. | 158 // for the encoding format. |
| 157 Bind(&if_smi_handler); | 159 Bind(&if_smi_handler); |
| 158 { | 160 { |
| 159 HandleLoadICSmiHandlerCase(p, var_holder.value(), var_smi_handler.value(), | 161 HandleLoadICSmiHandlerCase(p, var_holder.value(), var_smi_handler.value(), |
| 160 miss, support_elements); | 162 miss, &direct_exit, support_elements); |
| 161 } | 163 } |
| 162 | 164 |
| 163 Bind(&try_proto_handler); | 165 Bind(&try_proto_handler); |
| 164 { | 166 { |
| 165 GotoIf(IsCodeMap(LoadMap(handler)), &call_handler); | 167 GotoIf(IsCodeMap(LoadMap(handler)), &call_handler); |
| 166 HandleLoadICProtoHandlerCase(p, handler, &var_holder, &var_smi_handler, | 168 HandleLoadICProtoHandlerCase(p, handler, &var_holder, &var_smi_handler, |
| 167 &if_smi_handler, miss, false); | 169 &if_smi_handler, miss, &direct_exit, false); |
| 168 } | 170 } |
| 169 | 171 |
| 170 Bind(&call_handler); | 172 Bind(&call_handler); |
| 171 { | 173 { |
| 172 typedef LoadWithVectorDescriptor Descriptor; | 174 typedef LoadWithVectorDescriptor Descriptor; |
| 173 TailCallStub(Descriptor(isolate()), handler, p->context, p->receiver, | 175 TailCallStub(Descriptor(isolate()), handler, p->context, p->receiver, |
| 174 p->name, p->slot, p->vector); | 176 p->name, p->slot, p->vector); |
| 175 } | 177 } |
| 176 } | 178 } |
| 177 | 179 |
| 178 void AccessorAssembler::HandleLoadICSmiHandlerCase( | 180 void AccessorAssembler::HandleLoadICSmiHandlerCase( |
| 179 const LoadICParameters* p, Node* holder, Node* smi_handler, Label* miss, | 181 const LoadICParameters* p, Node* holder, Node* smi_handler, Label* miss, |
| 180 ElementSupport support_elements) { | 182 ExitPoint* exit_point, ElementSupport support_elements) { |
| 181 Variable var_double_value(this, MachineRepresentation::kFloat64); | 183 Variable var_double_value(this, MachineRepresentation::kFloat64); |
| 182 Label rebox_double(this, &var_double_value); | 184 Label rebox_double(this, &var_double_value); |
| 183 | 185 |
| 184 Node* handler_word = SmiUntag(smi_handler); | 186 Node* handler_word = SmiUntag(smi_handler); |
| 185 Node* handler_kind = DecodeWord<LoadHandler::KindBits>(handler_word); | 187 Node* handler_kind = DecodeWord<LoadHandler::KindBits>(handler_word); |
| 186 if (support_elements == kSupportElements) { | 188 if (support_elements == kSupportElements) { |
| 187 Label property(this); | 189 Label property(this); |
| 188 GotoUnless( | 190 GotoUnless( |
| 189 WordEqual(handler_kind, IntPtrConstant(LoadHandler::kForElements)), | 191 WordEqual(handler_kind, IntPtrConstant(LoadHandler::kForElements)), |
| 190 &property); | 192 &property); |
| 191 | 193 |
| 192 Comment("element_load"); | 194 Comment("element_load"); |
| 193 Node* intptr_index = TryToIntptr(p->name, miss); | 195 Node* intptr_index = TryToIntptr(p->name, miss); |
| 194 Node* elements = LoadElements(holder); | 196 Node* elements = LoadElements(holder); |
| 195 Node* is_jsarray_condition = | 197 Node* is_jsarray_condition = |
| 196 IsSetWord<LoadHandler::IsJsArrayBits>(handler_word); | 198 IsSetWord<LoadHandler::IsJsArrayBits>(handler_word); |
| 197 Node* elements_kind = | 199 Node* elements_kind = |
| 198 DecodeWord32FromWord<LoadHandler::ElementsKindBits>(handler_word); | 200 DecodeWord32FromWord<LoadHandler::ElementsKindBits>(handler_word); |
| 199 Label if_hole(this), unimplemented_elements_kind(this); | 201 Label if_hole(this), unimplemented_elements_kind(this); |
| 200 Label* out_of_bounds = miss; | 202 Label* out_of_bounds = miss; |
| 201 EmitElementLoad(holder, elements, elements_kind, intptr_index, | 203 EmitElementLoad(holder, elements, elements_kind, intptr_index, |
| 202 is_jsarray_condition, &if_hole, &rebox_double, | 204 is_jsarray_condition, &if_hole, &rebox_double, |
| 203 &var_double_value, &unimplemented_elements_kind, | 205 &var_double_value, &unimplemented_elements_kind, |
| 204 out_of_bounds, miss); | 206 out_of_bounds, miss, exit_point); |
| 205 | 207 |
| 206 Bind(&unimplemented_elements_kind); | 208 Bind(&unimplemented_elements_kind); |
| 207 { | 209 { |
| 208 // Smi handlers should only be installed for supported elements kinds. | 210 // Smi handlers should only be installed for supported elements kinds. |
| 209 // Crash if we get here. | 211 // Crash if we get here. |
| 210 DebugBreak(); | 212 DebugBreak(); |
| 211 Goto(miss); | 213 Goto(miss); |
| 212 } | 214 } |
| 213 | 215 |
| 214 Bind(&if_hole); | 216 Bind(&if_hole); |
| 215 { | 217 { |
| 216 Comment("convert hole"); | 218 Comment("convert hole"); |
| 217 GotoUnless(IsSetWord<LoadHandler::ConvertHoleBits>(handler_word), miss); | 219 GotoUnless(IsSetWord<LoadHandler::ConvertHoleBits>(handler_word), miss); |
| 218 Node* protector_cell = LoadRoot(Heap::kArrayProtectorRootIndex); | 220 Node* protector_cell = LoadRoot(Heap::kArrayProtectorRootIndex); |
| 219 DCHECK(isolate()->heap()->array_protector()->IsPropertyCell()); | 221 DCHECK(isolate()->heap()->array_protector()->IsPropertyCell()); |
| 220 GotoUnless( | 222 GotoUnless( |
| 221 WordEqual(LoadObjectField(protector_cell, PropertyCell::kValueOffset), | 223 WordEqual(LoadObjectField(protector_cell, PropertyCell::kValueOffset), |
| 222 SmiConstant(Smi::FromInt(Isolate::kProtectorValid))), | 224 SmiConstant(Smi::FromInt(Isolate::kProtectorValid))), |
| 223 miss); | 225 miss); |
| 224 Return(UndefinedConstant()); | 226 exit_point->Return(UndefinedConstant()); |
| 225 } | 227 } |
| 226 | 228 |
| 227 Bind(&property); | 229 Bind(&property); |
| 228 Comment("property_load"); | 230 Comment("property_load"); |
| 229 } | 231 } |
| 230 | 232 |
| 231 Label constant(this), field(this); | 233 Label constant(this), field(this); |
| 232 Branch(WordEqual(handler_kind, IntPtrConstant(LoadHandler::kForFields)), | 234 Branch(WordEqual(handler_kind, IntPtrConstant(LoadHandler::kForFields)), |
| 233 &field, &constant); | 235 &field, &constant); |
| 234 | 236 |
| 235 Bind(&field); | 237 Bind(&field); |
| 236 { | 238 { |
| 237 Comment("field_load"); | 239 Comment("field_load"); |
| 238 Node* offset = DecodeWord<LoadHandler::FieldOffsetBits>(handler_word); | 240 Node* offset = DecodeWord<LoadHandler::FieldOffsetBits>(handler_word); |
| 239 | 241 |
| 240 Label inobject(this), out_of_object(this); | 242 Label inobject(this), out_of_object(this); |
| 241 Branch(IsSetWord<LoadHandler::IsInobjectBits>(handler_word), &inobject, | 243 Branch(IsSetWord<LoadHandler::IsInobjectBits>(handler_word), &inobject, |
| 242 &out_of_object); | 244 &out_of_object); |
| 243 | 245 |
| 244 Bind(&inobject); | 246 Bind(&inobject); |
| 245 { | 247 { |
| 246 Label is_double(this); | 248 Label is_double(this); |
| 247 GotoIf(IsSetWord<LoadHandler::IsDoubleBits>(handler_word), &is_double); | 249 GotoIf(IsSetWord<LoadHandler::IsDoubleBits>(handler_word), &is_double); |
| 248 Return(LoadObjectField(holder, offset)); | 250 exit_point->Return(LoadObjectField(holder, offset)); |
| 249 | 251 |
| 250 Bind(&is_double); | 252 Bind(&is_double); |
| 251 if (FLAG_unbox_double_fields) { | 253 if (FLAG_unbox_double_fields) { |
| 252 var_double_value.Bind( | 254 var_double_value.Bind( |
| 253 LoadObjectField(holder, offset, MachineType::Float64())); | 255 LoadObjectField(holder, offset, MachineType::Float64())); |
| 254 } else { | 256 } else { |
| 255 Node* mutable_heap_number = LoadObjectField(holder, offset); | 257 Node* mutable_heap_number = LoadObjectField(holder, offset); |
| 256 var_double_value.Bind(LoadHeapNumberValue(mutable_heap_number)); | 258 var_double_value.Bind(LoadHeapNumberValue(mutable_heap_number)); |
| 257 } | 259 } |
| 258 Goto(&rebox_double); | 260 Goto(&rebox_double); |
| 259 } | 261 } |
| 260 | 262 |
| 261 Bind(&out_of_object); | 263 Bind(&out_of_object); |
| 262 { | 264 { |
| 263 Label is_double(this); | 265 Label is_double(this); |
| 264 Node* properties = LoadProperties(holder); | 266 Node* properties = LoadProperties(holder); |
| 265 Node* value = LoadObjectField(properties, offset); | 267 Node* value = LoadObjectField(properties, offset); |
| 266 GotoIf(IsSetWord<LoadHandler::IsDoubleBits>(handler_word), &is_double); | 268 GotoIf(IsSetWord<LoadHandler::IsDoubleBits>(handler_word), &is_double); |
| 267 Return(value); | 269 exit_point->Return(value); |
| 268 | 270 |
| 269 Bind(&is_double); | 271 Bind(&is_double); |
| 270 var_double_value.Bind(LoadHeapNumberValue(value)); | 272 var_double_value.Bind(LoadHeapNumberValue(value)); |
| 271 Goto(&rebox_double); | 273 Goto(&rebox_double); |
| 272 } | 274 } |
| 273 | 275 |
| 274 Bind(&rebox_double); | 276 Bind(&rebox_double); |
| 275 Return(AllocateHeapNumberWithValue(var_double_value.value())); | 277 exit_point->Return(AllocateHeapNumberWithValue(var_double_value.value())); |
| 276 } | 278 } |
| 277 | 279 |
| 278 Bind(&constant); | 280 Bind(&constant); |
| 279 { | 281 { |
| 280 Comment("constant_load"); | 282 Comment("constant_load"); |
| 281 Node* descriptors = LoadMapDescriptors(LoadMap(holder)); | 283 Node* descriptors = LoadMapDescriptors(LoadMap(holder)); |
| 282 Node* descriptor = | 284 Node* descriptor = |
| 283 DecodeWord<LoadHandler::DescriptorValueIndexBits>(handler_word); | 285 DecodeWord<LoadHandler::DescriptorValueIndexBits>(handler_word); |
| 284 CSA_ASSERT(this, | 286 CSA_ASSERT(this, |
| 285 UintPtrLessThan(descriptor, | 287 UintPtrLessThan(descriptor, |
| 286 LoadAndUntagFixedArrayBaseLength(descriptors))); | 288 LoadAndUntagFixedArrayBaseLength(descriptors))); |
| 287 Node* value = LoadFixedArrayElement(descriptors, descriptor); | 289 Node* value = LoadFixedArrayElement(descriptors, descriptor); |
| 288 | 290 |
| 289 Label if_accessor_info(this); | 291 Label if_accessor_info(this); |
| 290 GotoIf(IsSetWord<LoadHandler::IsAccessorInfoBits>(handler_word), | 292 GotoIf(IsSetWord<LoadHandler::IsAccessorInfoBits>(handler_word), |
| 291 &if_accessor_info); | 293 &if_accessor_info); |
| 292 Return(value); | 294 exit_point->Return(value); |
| 293 | 295 |
| 294 Bind(&if_accessor_info); | 296 Bind(&if_accessor_info); |
| 295 Callable callable = CodeFactory::ApiGetter(isolate()); | 297 Callable callable = CodeFactory::ApiGetter(isolate()); |
| 296 TailCallStub(callable, p->context, p->receiver, holder, value); | 298 exit_point->ReturnStub(callable, p->context, p->receiver, holder, value); |
| 297 } | 299 } |
| 298 } | 300 } |
| 299 | 301 |
| 300 void AccessorAssembler::HandleLoadICProtoHandlerCase( | 302 void AccessorAssembler::HandleLoadICProtoHandlerCase( |
| 301 const LoadICParameters* p, Node* handler, Variable* var_holder, | 303 const LoadICParameters* p, Node* handler, Variable* var_holder, |
| 302 Variable* var_smi_handler, Label* if_smi_handler, Label* miss, | 304 Variable* var_smi_handler, Label* if_smi_handler, Label* miss, |
| 303 bool throw_reference_error_if_nonexistent) { | 305 ExitPoint* exit_point, bool throw_reference_error_if_nonexistent) { |
| 304 DCHECK_EQ(MachineRepresentation::kTagged, var_holder->rep()); | 306 DCHECK_EQ(MachineRepresentation::kTagged, var_holder->rep()); |
| 305 DCHECK_EQ(MachineRepresentation::kTagged, var_smi_handler->rep()); | 307 DCHECK_EQ(MachineRepresentation::kTagged, var_smi_handler->rep()); |
| 306 | 308 |
| 307 // IC dispatchers rely on these assumptions to be held. | 309 // IC dispatchers rely on these assumptions to be held. |
| 308 STATIC_ASSERT(FixedArray::kLengthOffset == LoadHandler::kHolderCellOffset); | 310 STATIC_ASSERT(FixedArray::kLengthOffset == LoadHandler::kHolderCellOffset); |
| 309 DCHECK_EQ(FixedArray::OffsetOfElementAt(LoadHandler::kSmiHandlerIndex), | 311 DCHECK_EQ(FixedArray::OffsetOfElementAt(LoadHandler::kSmiHandlerIndex), |
| 310 LoadHandler::kSmiHandlerOffset); | 312 LoadHandler::kSmiHandlerOffset); |
| 311 DCHECK_EQ(FixedArray::OffsetOfElementAt(LoadHandler::kValidityCellIndex), | 313 DCHECK_EQ(FixedArray::OffsetOfElementAt(LoadHandler::kValidityCellIndex), |
| 312 LoadHandler::kValidityCellOffset); | 314 LoadHandler::kValidityCellOffset); |
| 313 | 315 |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 345 LoadObjectField(handler, LoadHandler::kHolderCellOffset); | 347 LoadObjectField(handler, LoadHandler::kHolderCellOffset); |
| 346 Label array_handler(this), tuple_handler(this); | 348 Label array_handler(this), tuple_handler(this); |
| 347 Branch(TaggedIsSmi(maybe_holder_cell), &array_handler, &tuple_handler); | 349 Branch(TaggedIsSmi(maybe_holder_cell), &array_handler, &tuple_handler); |
| 348 | 350 |
| 349 Bind(&tuple_handler); | 351 Bind(&tuple_handler); |
| 350 { | 352 { |
| 351 Label load_existent(this); | 353 Label load_existent(this); |
| 352 GotoIf(WordNotEqual(maybe_holder_cell, NullConstant()), &load_existent); | 354 GotoIf(WordNotEqual(maybe_holder_cell, NullConstant()), &load_existent); |
| 353 // This is a handler for a load of a non-existent value. | 355 // This is a handler for a load of a non-existent value. |
| 354 if (throw_reference_error_if_nonexistent) { | 356 if (throw_reference_error_if_nonexistent) { |
| 355 TailCallRuntime(Runtime::kThrowReferenceError, p->context, p->name); | 357 exit_point->ReturnRuntime(Runtime::kThrowReferenceError, p->context, |
| 358 p->name); | |
| 356 } else { | 359 } else { |
| 357 Return(UndefinedConstant()); | 360 exit_point->Return(UndefinedConstant()); |
| 358 } | 361 } |
| 359 | 362 |
| 360 Bind(&load_existent); | 363 Bind(&load_existent); |
| 361 Node* holder = LoadWeakCellValue(maybe_holder_cell); | 364 Node* holder = LoadWeakCellValue(maybe_holder_cell); |
| 362 // The |holder| is guaranteed to be alive at this point since we passed | 365 // The |holder| is guaranteed to be alive at this point since we passed |
| 363 // both the receiver map check and the validity cell check. | 366 // both the receiver map check and the validity cell check. |
| 364 CSA_ASSERT(this, WordNotEqual(holder, IntPtrConstant(0))); | 367 CSA_ASSERT(this, WordNotEqual(holder, IntPtrConstant(0))); |
| 365 | 368 |
| 366 var_holder->Bind(holder); | 369 var_holder->Bind(holder); |
| 367 var_smi_handler->Bind(smi_handler); | 370 var_smi_handler->Bind(smi_handler); |
| 368 Goto(if_smi_handler); | 371 Goto(if_smi_handler); |
| 369 } | 372 } |
| 370 | 373 |
| 371 Bind(&array_handler); | 374 Bind(&array_handler); |
| 372 { | 375 { |
| 373 TailCallStub(CodeFactory::LoadICProtoArray( | 376 exit_point->ReturnStub(CodeFactory::LoadICProtoArray( |
| 374 isolate(), throw_reference_error_if_nonexistent), | 377 isolate(), throw_reference_error_if_nonexistent), |
| 375 p->context, p->receiver, p->name, p->slot, p->vector, handler); | 378 p->context, p->receiver, p->name, p->slot, p->vector, |
| 379 handler); | |
| 376 } | 380 } |
| 377 } | 381 } |
| 378 | 382 |
| 379 Node* AccessorAssembler::EmitLoadICProtoArrayCheck( | 383 Node* AccessorAssembler::EmitLoadICProtoArrayCheck( |
| 380 const LoadICParameters* p, Node* handler, Node* handler_length, | 384 const LoadICParameters* p, Node* handler, Node* handler_length, |
| 381 Node* handler_flags, Label* miss, | 385 Node* handler_flags, Label* miss, |
| 382 bool throw_reference_error_if_nonexistent) { | 386 bool throw_reference_error_if_nonexistent) { |
| 383 Variable start_index(this, MachineType::PointerRepresentation()); | 387 Variable start_index(this, MachineType::PointerRepresentation()); |
| 384 start_index.Bind(IntPtrConstant(LoadHandler::kFirstPrototypeIndex)); | 388 start_index.Bind(IntPtrConstant(LoadHandler::kFirstPrototypeIndex)); |
| 385 | 389 |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 433 Node* holder = LoadWeakCellValue(maybe_holder_cell); | 437 Node* holder = LoadWeakCellValue(maybe_holder_cell); |
| 434 // The |holder| is guaranteed to be alive at this point since we passed | 438 // The |holder| is guaranteed to be alive at this point since we passed |
| 435 // the receiver map check, the validity cell check and the prototype chain | 439 // the receiver map check, the validity cell check and the prototype chain |
| 436 // check. | 440 // check. |
| 437 CSA_ASSERT(this, WordNotEqual(holder, IntPtrConstant(0))); | 441 CSA_ASSERT(this, WordNotEqual(holder, IntPtrConstant(0))); |
| 438 return holder; | 442 return holder; |
| 439 } | 443 } |
| 440 | 444 |
| 441 void AccessorAssembler::HandleLoadGlobalICHandlerCase( | 445 void AccessorAssembler::HandleLoadGlobalICHandlerCase( |
| 442 const LoadICParameters* pp, Node* handler, Label* miss, | 446 const LoadICParameters* pp, Node* handler, Label* miss, |
| 443 bool throw_reference_error_if_nonexistent) { | 447 ExitPoint* exit_point, bool throw_reference_error_if_nonexistent) { |
| 444 LoadICParameters p = *pp; | 448 LoadICParameters p = *pp; |
| 445 DCHECK_NULL(p.receiver); | 449 DCHECK_NULL(p.receiver); |
| 446 Node* native_context = LoadNativeContext(p.context); | 450 Node* native_context = LoadNativeContext(p.context); |
| 447 p.receiver = LoadContextElement(native_context, Context::EXTENSION_INDEX); | 451 p.receiver = LoadContextElement(native_context, Context::EXTENSION_INDEX); |
| 448 | 452 |
| 449 Variable var_holder(this, MachineRepresentation::kTagged); | 453 Variable var_holder(this, MachineRepresentation::kTagged); |
| 450 Variable var_smi_handler(this, MachineRepresentation::kTagged); | 454 Variable var_smi_handler(this, MachineRepresentation::kTagged); |
| 451 Label if_smi_handler(this); | 455 Label if_smi_handler(this); |
| 452 HandleLoadICProtoHandlerCase(&p, handler, &var_holder, &var_smi_handler, | 456 HandleLoadICProtoHandlerCase(&p, handler, &var_holder, &var_smi_handler, |
| 453 &if_smi_handler, miss, | 457 &if_smi_handler, miss, exit_point, |
| 454 throw_reference_error_if_nonexistent); | 458 throw_reference_error_if_nonexistent); |
| 455 Bind(&if_smi_handler); | 459 Bind(&if_smi_handler); |
| 456 HandleLoadICSmiHandlerCase(&p, var_holder.value(), var_smi_handler.value(), | 460 HandleLoadICSmiHandlerCase(&p, var_holder.value(), var_smi_handler.value(), |
| 457 miss, kOnlyProperties); | 461 miss, exit_point, kOnlyProperties); |
| 458 } | 462 } |
| 459 | 463 |
| 460 void AccessorAssembler::HandleStoreICHandlerCase( | 464 void AccessorAssembler::HandleStoreICHandlerCase( |
| 461 const StoreICParameters* p, Node* handler, Label* miss, | 465 const StoreICParameters* p, Node* handler, Label* miss, |
| 462 ElementSupport support_elements) { | 466 ElementSupport support_elements) { |
| 463 Label if_smi_handler(this), if_nonsmi_handler(this); | 467 Label if_smi_handler(this), if_nonsmi_handler(this); |
| 464 Label if_proto_handler(this), if_element_handler(this), call_handler(this); | 468 Label if_proto_handler(this), if_element_handler(this), call_handler(this); |
| 465 | 469 |
| 466 Branch(TaggedIsSmi(handler), &if_smi_handler, &if_nonsmi_handler); | 470 Branch(TaggedIsSmi(handler), &if_smi_handler, &if_nonsmi_handler); |
| 467 | 471 |
| (...skipping 381 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 849 } | 853 } |
| 850 Bind(&if_array); | 854 Bind(&if_array); |
| 851 { | 855 { |
| 852 var_length.Bind(SmiUntag(LoadJSArrayLength(object))); | 856 var_length.Bind(SmiUntag(LoadJSArrayLength(object))); |
| 853 Goto(&length_loaded); | 857 Goto(&length_loaded); |
| 854 } | 858 } |
| 855 Bind(&length_loaded); | 859 Bind(&length_loaded); |
| 856 GotoUnless(UintPtrLessThan(intptr_index, var_length.value()), miss); | 860 GotoUnless(UintPtrLessThan(intptr_index, var_length.value()), miss); |
| 857 } | 861 } |
| 858 | 862 |
| 859 void AccessorAssembler::EmitElementLoad(Node* object, Node* elements, | 863 void AccessorAssembler::EmitElementLoad( |
| 860 Node* elements_kind, Node* intptr_index, | 864 Node* object, Node* elements, Node* elements_kind, Node* intptr_index, |
| 861 Node* is_jsarray_condition, | 865 Node* is_jsarray_condition, Label* if_hole, Label* rebox_double, |
| 862 Label* if_hole, Label* rebox_double, | 866 Variable* var_double_value, Label* unimplemented_elements_kind, |
| 863 Variable* var_double_value, | 867 Label* out_of_bounds, Label* miss, ExitPoint* exit_point) { |
| 864 Label* unimplemented_elements_kind, | |
| 865 Label* out_of_bounds, Label* miss) { | |
| 866 Label if_typed_array(this), if_fast_packed(this), if_fast_holey(this), | 868 Label if_typed_array(this), if_fast_packed(this), if_fast_holey(this), |
| 867 if_fast_double(this), if_fast_holey_double(this), if_nonfast(this), | 869 if_fast_double(this), if_fast_holey_double(this), if_nonfast(this), |
| 868 if_dictionary(this); | 870 if_dictionary(this); |
| 869 GotoIf( | 871 GotoIf( |
| 870 Int32GreaterThan(elements_kind, Int32Constant(LAST_FAST_ELEMENTS_KIND)), | 872 Int32GreaterThan(elements_kind, Int32Constant(LAST_FAST_ELEMENTS_KIND)), |
| 871 &if_nonfast); | 873 &if_nonfast); |
| 872 | 874 |
| 873 EmitFastElementsBoundsCheck(object, elements, intptr_index, | 875 EmitFastElementsBoundsCheck(object, elements, intptr_index, |
| 874 is_jsarray_condition, out_of_bounds); | 876 is_jsarray_condition, out_of_bounds); |
| 875 int32_t kinds[] = {// Handled by if_fast_packed. | 877 int32_t kinds[] = {// Handled by if_fast_packed. |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 887 // FAST_DOUBLE_ELEMENTS | 889 // FAST_DOUBLE_ELEMENTS |
| 888 &if_fast_double, | 890 &if_fast_double, |
| 889 // FAST_HOLEY_DOUBLE_ELEMENTS | 891 // FAST_HOLEY_DOUBLE_ELEMENTS |
| 890 &if_fast_holey_double}; | 892 &if_fast_holey_double}; |
| 891 Switch(elements_kind, unimplemented_elements_kind, kinds, labels, | 893 Switch(elements_kind, unimplemented_elements_kind, kinds, labels, |
| 892 arraysize(kinds)); | 894 arraysize(kinds)); |
| 893 | 895 |
| 894 Bind(&if_fast_packed); | 896 Bind(&if_fast_packed); |
| 895 { | 897 { |
| 896 Comment("fast packed elements"); | 898 Comment("fast packed elements"); |
| 897 Return(LoadFixedArrayElement(elements, intptr_index)); | 899 exit_point->Return(LoadFixedArrayElement(elements, intptr_index)); |
| 898 } | 900 } |
| 899 | 901 |
| 900 Bind(&if_fast_holey); | 902 Bind(&if_fast_holey); |
| 901 { | 903 { |
| 902 Comment("fast holey elements"); | 904 Comment("fast holey elements"); |
| 903 Node* element = LoadFixedArrayElement(elements, intptr_index); | 905 Node* element = LoadFixedArrayElement(elements, intptr_index); |
| 904 GotoIf(WordEqual(element, TheHoleConstant()), if_hole); | 906 GotoIf(WordEqual(element, TheHoleConstant()), if_hole); |
| 905 Return(element); | 907 exit_point->Return(element); |
| 906 } | 908 } |
| 907 | 909 |
| 908 Bind(&if_fast_double); | 910 Bind(&if_fast_double); |
| 909 { | 911 { |
| 910 Comment("packed double elements"); | 912 Comment("packed double elements"); |
| 911 var_double_value->Bind(LoadFixedDoubleArrayElement(elements, intptr_index, | 913 var_double_value->Bind(LoadFixedDoubleArrayElement(elements, intptr_index, |
| 912 MachineType::Float64())); | 914 MachineType::Float64())); |
| 913 Goto(rebox_double); | 915 Goto(rebox_double); |
| 914 } | 916 } |
| 915 | 917 |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 947 // Check that the value is a data property. | 949 // Check that the value is a data property. |
| 948 Node* details_index = EntryToIndex<SeededNumberDictionary>( | 950 Node* details_index = EntryToIndex<SeededNumberDictionary>( |
| 949 var_entry.value(), SeededNumberDictionary::kEntryDetailsIndex); | 951 var_entry.value(), SeededNumberDictionary::kEntryDetailsIndex); |
| 950 Node* details = SmiToWord32(LoadFixedArrayElement(elements, details_index)); | 952 Node* details = SmiToWord32(LoadFixedArrayElement(elements, details_index)); |
| 951 Node* kind = DecodeWord32<PropertyDetails::KindField>(details); | 953 Node* kind = DecodeWord32<PropertyDetails::KindField>(details); |
| 952 // TODO(jkummerow): Support accessors without missing? | 954 // TODO(jkummerow): Support accessors without missing? |
| 953 GotoUnless(Word32Equal(kind, Int32Constant(kData)), miss); | 955 GotoUnless(Word32Equal(kind, Int32Constant(kData)), miss); |
| 954 // Finally, load the value. | 956 // Finally, load the value. |
| 955 Node* value_index = EntryToIndex<SeededNumberDictionary>( | 957 Node* value_index = EntryToIndex<SeededNumberDictionary>( |
| 956 var_entry.value(), SeededNumberDictionary::kEntryValueIndex); | 958 var_entry.value(), SeededNumberDictionary::kEntryValueIndex); |
| 957 Return(LoadFixedArrayElement(elements, value_index)); | 959 exit_point->Return(LoadFixedArrayElement(elements, value_index)); |
| 958 } | 960 } |
| 959 | 961 |
| 960 Bind(&if_typed_array); | 962 Bind(&if_typed_array); |
| 961 { | 963 { |
| 962 Comment("typed elements"); | 964 Comment("typed elements"); |
| 963 // Check if buffer has been neutered. | 965 // Check if buffer has been neutered. |
| 964 Node* buffer = LoadObjectField(object, JSArrayBufferView::kBufferOffset); | 966 Node* buffer = LoadObjectField(object, JSArrayBufferView::kBufferOffset); |
| 965 GotoIf(IsDetachedBuffer(buffer), miss); | 967 GotoIf(IsDetachedBuffer(buffer), miss); |
| 966 | 968 |
| 967 // Bounds check. | 969 // Bounds check. |
| (...skipping 25 matching lines...) Expand all Loading... | |
| 993 LAST_FIXED_TYPED_ARRAY_ELEMENTS_KIND - | 995 LAST_FIXED_TYPED_ARRAY_ELEMENTS_KIND - |
| 994 FIRST_FIXED_TYPED_ARRAY_ELEMENTS_KIND + 1; | 996 FIRST_FIXED_TYPED_ARRAY_ELEMENTS_KIND + 1; |
| 995 DCHECK_EQ(kTypedElementsKindCount, arraysize(elements_kinds)); | 997 DCHECK_EQ(kTypedElementsKindCount, arraysize(elements_kinds)); |
| 996 DCHECK_EQ(kTypedElementsKindCount, arraysize(elements_kind_labels)); | 998 DCHECK_EQ(kTypedElementsKindCount, arraysize(elements_kind_labels)); |
| 997 Switch(elements_kind, miss, elements_kinds, elements_kind_labels, | 999 Switch(elements_kind, miss, elements_kinds, elements_kind_labels, |
| 998 kTypedElementsKindCount); | 1000 kTypedElementsKindCount); |
| 999 Bind(&uint8_elements); | 1001 Bind(&uint8_elements); |
| 1000 { | 1002 { |
| 1001 Comment("UINT8_ELEMENTS"); // Handles UINT8_CLAMPED_ELEMENTS too. | 1003 Comment("UINT8_ELEMENTS"); // Handles UINT8_CLAMPED_ELEMENTS too. |
| 1002 Node* element = Load(MachineType::Uint8(), backing_store, intptr_index); | 1004 Node* element = Load(MachineType::Uint8(), backing_store, intptr_index); |
| 1003 Return(SmiFromWord32(element)); | 1005 exit_point->Return(SmiFromWord32(element)); |
| 1004 } | 1006 } |
| 1005 Bind(&int8_elements); | 1007 Bind(&int8_elements); |
| 1006 { | 1008 { |
| 1007 Comment("INT8_ELEMENTS"); | 1009 Comment("INT8_ELEMENTS"); |
| 1008 Node* element = Load(MachineType::Int8(), backing_store, intptr_index); | 1010 Node* element = Load(MachineType::Int8(), backing_store, intptr_index); |
| 1009 Return(SmiFromWord32(element)); | 1011 exit_point->Return(SmiFromWord32(element)); |
| 1010 } | 1012 } |
| 1011 Bind(&uint16_elements); | 1013 Bind(&uint16_elements); |
| 1012 { | 1014 { |
| 1013 Comment("UINT16_ELEMENTS"); | 1015 Comment("UINT16_ELEMENTS"); |
| 1014 Node* index = WordShl(intptr_index, IntPtrConstant(1)); | 1016 Node* index = WordShl(intptr_index, IntPtrConstant(1)); |
| 1015 Node* element = Load(MachineType::Uint16(), backing_store, index); | 1017 Node* element = Load(MachineType::Uint16(), backing_store, index); |
| 1016 Return(SmiFromWord32(element)); | 1018 exit_point->Return(SmiFromWord32(element)); |
| 1017 } | 1019 } |
| 1018 Bind(&int16_elements); | 1020 Bind(&int16_elements); |
| 1019 { | 1021 { |
| 1020 Comment("INT16_ELEMENTS"); | 1022 Comment("INT16_ELEMENTS"); |
| 1021 Node* index = WordShl(intptr_index, IntPtrConstant(1)); | 1023 Node* index = WordShl(intptr_index, IntPtrConstant(1)); |
| 1022 Node* element = Load(MachineType::Int16(), backing_store, index); | 1024 Node* element = Load(MachineType::Int16(), backing_store, index); |
| 1023 Return(SmiFromWord32(element)); | 1025 exit_point->Return(SmiFromWord32(element)); |
| 1024 } | 1026 } |
| 1025 Bind(&uint32_elements); | 1027 Bind(&uint32_elements); |
| 1026 { | 1028 { |
| 1027 Comment("UINT32_ELEMENTS"); | 1029 Comment("UINT32_ELEMENTS"); |
| 1028 Node* index = WordShl(intptr_index, IntPtrConstant(2)); | 1030 Node* index = WordShl(intptr_index, IntPtrConstant(2)); |
| 1029 Node* element = Load(MachineType::Uint32(), backing_store, index); | 1031 Node* element = Load(MachineType::Uint32(), backing_store, index); |
| 1030 Return(ChangeUint32ToTagged(element)); | 1032 exit_point->Return(ChangeUint32ToTagged(element)); |
| 1031 } | 1033 } |
| 1032 Bind(&int32_elements); | 1034 Bind(&int32_elements); |
| 1033 { | 1035 { |
| 1034 Comment("INT32_ELEMENTS"); | 1036 Comment("INT32_ELEMENTS"); |
| 1035 Node* index = WordShl(intptr_index, IntPtrConstant(2)); | 1037 Node* index = WordShl(intptr_index, IntPtrConstant(2)); |
| 1036 Node* element = Load(MachineType::Int32(), backing_store, index); | 1038 Node* element = Load(MachineType::Int32(), backing_store, index); |
| 1037 Return(ChangeInt32ToTagged(element)); | 1039 exit_point->Return(ChangeInt32ToTagged(element)); |
| 1038 } | 1040 } |
| 1039 Bind(&float32_elements); | 1041 Bind(&float32_elements); |
| 1040 { | 1042 { |
| 1041 Comment("FLOAT32_ELEMENTS"); | 1043 Comment("FLOAT32_ELEMENTS"); |
| 1042 Node* index = WordShl(intptr_index, IntPtrConstant(2)); | 1044 Node* index = WordShl(intptr_index, IntPtrConstant(2)); |
| 1043 Node* element = Load(MachineType::Float32(), backing_store, index); | 1045 Node* element = Load(MachineType::Float32(), backing_store, index); |
| 1044 var_double_value->Bind(ChangeFloat32ToFloat64(element)); | 1046 var_double_value->Bind(ChangeFloat32ToFloat64(element)); |
| 1045 Goto(rebox_double); | 1047 Goto(rebox_double); |
| 1046 } | 1048 } |
| 1047 Bind(&float64_elements); | 1049 Bind(&float64_elements); |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1094 Label done(this); | 1096 Label done(this); |
| 1095 NameDictionaryLookup<NameDictionary>(properties, name, miss, &var_name_index, | 1097 NameDictionaryLookup<NameDictionary>(properties, name, miss, &var_name_index, |
| 1096 &done); | 1098 &done); |
| 1097 Bind(&done); | 1099 Bind(&done); |
| 1098 } | 1100 } |
| 1099 | 1101 |
| 1100 void AccessorAssembler::GenericElementLoad(Node* receiver, Node* receiver_map, | 1102 void AccessorAssembler::GenericElementLoad(Node* receiver, Node* receiver_map, |
| 1101 Node* instance_type, Node* index, | 1103 Node* instance_type, Node* index, |
| 1102 Label* slow) { | 1104 Label* slow) { |
| 1103 Comment("integer index"); | 1105 Comment("integer index"); |
| 1106 | |
| 1107 ExitPoint direct_exit(this); | |
| 1108 | |
| 1104 Label if_element_hole(this), if_oob(this); | 1109 Label if_element_hole(this), if_oob(this); |
| 1105 // Receivers requiring non-standard element accesses (interceptors, access | 1110 // Receivers requiring non-standard element accesses (interceptors, access |
| 1106 // checks, strings and string wrappers, proxies) are handled in the runtime. | 1111 // checks, strings and string wrappers, proxies) are handled in the runtime. |
| 1107 GotoIf(Int32LessThanOrEqual(instance_type, | 1112 GotoIf(Int32LessThanOrEqual(instance_type, |
| 1108 Int32Constant(LAST_CUSTOM_ELEMENTS_RECEIVER)), | 1113 Int32Constant(LAST_CUSTOM_ELEMENTS_RECEIVER)), |
| 1109 slow); | 1114 slow); |
| 1110 Node* elements = LoadElements(receiver); | 1115 Node* elements = LoadElements(receiver); |
| 1111 Node* elements_kind = LoadMapElementsKind(receiver_map); | 1116 Node* elements_kind = LoadMapElementsKind(receiver_map); |
| 1112 Node* is_jsarray_condition = | 1117 Node* is_jsarray_condition = |
| 1113 Word32Equal(instance_type, Int32Constant(JS_ARRAY_TYPE)); | 1118 Word32Equal(instance_type, Int32Constant(JS_ARRAY_TYPE)); |
| 1114 Variable var_double_value(this, MachineRepresentation::kFloat64); | 1119 Variable var_double_value(this, MachineRepresentation::kFloat64); |
| 1115 Label rebox_double(this, &var_double_value); | 1120 Label rebox_double(this, &var_double_value); |
| 1116 | 1121 |
| 1117 // Unimplemented elements kinds fall back to a runtime call. | 1122 // Unimplemented elements kinds fall back to a runtime call. |
| 1118 Label* unimplemented_elements_kind = slow; | 1123 Label* unimplemented_elements_kind = slow; |
| 1119 IncrementCounter(isolate()->counters()->ic_keyed_load_generic_smi(), 1); | 1124 IncrementCounter(isolate()->counters()->ic_keyed_load_generic_smi(), 1); |
| 1120 EmitElementLoad(receiver, elements, elements_kind, index, | 1125 EmitElementLoad(receiver, elements, elements_kind, index, |
| 1121 is_jsarray_condition, &if_element_hole, &rebox_double, | 1126 is_jsarray_condition, &if_element_hole, &rebox_double, |
| 1122 &var_double_value, unimplemented_elements_kind, &if_oob, | 1127 &var_double_value, unimplemented_elements_kind, &if_oob, slow, |
| 1123 slow); | 1128 &direct_exit); |
| 1124 | 1129 |
| 1125 Bind(&rebox_double); | 1130 Bind(&rebox_double); |
| 1126 Return(AllocateHeapNumberWithValue(var_double_value.value())); | 1131 Return(AllocateHeapNumberWithValue(var_double_value.value())); |
| 1127 | 1132 |
| 1128 Bind(&if_oob); | 1133 Bind(&if_oob); |
| 1129 { | 1134 { |
| 1130 Comment("out of bounds"); | 1135 Comment("out of bounds"); |
| 1131 // Negative keys can't take the fast OOB path. | 1136 // Negative keys can't take the fast OOB path. |
| 1132 GotoIf(IntPtrLessThan(index, IntPtrConstant(0)), slow); | 1137 GotoIf(IntPtrLessThan(index, IntPtrConstant(0)), slow); |
| 1133 // Positive OOB indices are effectively the same as hole loads. | 1138 // Positive OOB indices are effectively the same as hole loads. |
| (...skipping 318 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1452 } | 1457 } |
| 1453 } | 1458 } |
| 1454 | 1459 |
| 1455 void AccessorAssembler::LoadICProtoArray( | 1460 void AccessorAssembler::LoadICProtoArray( |
| 1456 const LoadICParameters* p, Node* handler, | 1461 const LoadICParameters* p, Node* handler, |
| 1457 bool throw_reference_error_if_nonexistent) { | 1462 bool throw_reference_error_if_nonexistent) { |
| 1458 Label miss(this); | 1463 Label miss(this); |
| 1459 CSA_ASSERT(this, Word32BinaryNot(TaggedIsSmi(handler))); | 1464 CSA_ASSERT(this, Word32BinaryNot(TaggedIsSmi(handler))); |
| 1460 CSA_ASSERT(this, IsFixedArrayMap(LoadMap(handler))); | 1465 CSA_ASSERT(this, IsFixedArrayMap(LoadMap(handler))); |
| 1461 | 1466 |
| 1467 ExitPoint direct_exit(this); | |
| 1468 | |
| 1462 Node* smi_handler = LoadObjectField(handler, LoadHandler::kSmiHandlerOffset); | 1469 Node* smi_handler = LoadObjectField(handler, LoadHandler::kSmiHandlerOffset); |
| 1463 Node* handler_flags = SmiUntag(smi_handler); | 1470 Node* handler_flags = SmiUntag(smi_handler); |
| 1464 | 1471 |
| 1465 Node* handler_length = LoadAndUntagFixedArrayBaseLength(handler); | 1472 Node* handler_length = LoadAndUntagFixedArrayBaseLength(handler); |
| 1466 | 1473 |
| 1467 Node* holder = | 1474 Node* holder = |
| 1468 EmitLoadICProtoArrayCheck(p, handler, handler_length, handler_flags, | 1475 EmitLoadICProtoArrayCheck(p, handler, handler_length, handler_flags, |
| 1469 &miss, throw_reference_error_if_nonexistent); | 1476 &miss, throw_reference_error_if_nonexistent); |
| 1470 | 1477 |
| 1471 HandleLoadICSmiHandlerCase(p, holder, smi_handler, &miss, kOnlyProperties); | 1478 HandleLoadICSmiHandlerCase(p, holder, smi_handler, &miss, &direct_exit, |
| 1479 kOnlyProperties); | |
| 1472 | 1480 |
| 1473 Bind(&miss); | 1481 Bind(&miss); |
| 1474 { | 1482 { |
| 1475 TailCallRuntime(Runtime::kLoadIC_Miss, p->context, p->receiver, p->name, | 1483 TailCallRuntime(Runtime::kLoadIC_Miss, p->context, p->receiver, p->name, |
| 1476 p->slot, p->vector); | 1484 p->slot, p->vector); |
| 1477 } | 1485 } |
| 1478 } | 1486 } |
| 1479 | 1487 |
| 1480 void AccessorAssembler::LoadGlobalIC(const LoadICParameters* p, | 1488 void AccessorAssembler::LoadGlobalICData(const LoadICParameters* p, |
|
Igor Sheludko
2017/02/08 15:26:31
LoadGlobalIC_TryPropertyCellCase(Node* vector, Nod
jgruber
2017/02/09 09:23:42
SG. I had it like this in an upcoming CL to omit u
| |
| 1481 TypeofMode typeof_mode) { | 1489 ExitPoint* exit_point, |
| 1482 Label try_handler(this), call_handler(this), miss(this); | 1490 Label* try_handler, Label* miss) { |
| 1491 Comment("LoadGlobalICData"); | |
|
Igor Sheludko
2017/02/08 15:26:31
Same here.
jgruber
2017/02/09 09:23:42
Done.
| |
| 1492 | |
| 1483 Node* weak_cell = | 1493 Node* weak_cell = |
| 1484 LoadFixedArrayElement(p->vector, p->slot, 0, SMI_PARAMETERS); | 1494 LoadFixedArrayElement(p->vector, p->slot, 0, SMI_PARAMETERS); |
| 1485 CSA_ASSERT(this, HasInstanceType(weak_cell, WEAK_CELL_TYPE)); | 1495 CSA_ASSERT(this, HasInstanceType(weak_cell, WEAK_CELL_TYPE)); |
| 1486 | 1496 |
| 1487 // Load value or try handler case if the {weak_cell} is cleared. | 1497 // Load value or try handler case if the {weak_cell} is cleared. |
| 1488 Node* property_cell = LoadWeakCellValue(weak_cell, &try_handler); | 1498 Node* property_cell = LoadWeakCellValue(weak_cell, try_handler); |
| 1489 CSA_ASSERT(this, HasInstanceType(property_cell, PROPERTY_CELL_TYPE)); | 1499 CSA_ASSERT(this, HasInstanceType(property_cell, PROPERTY_CELL_TYPE)); |
| 1490 | 1500 |
| 1491 Node* value = LoadObjectField(property_cell, PropertyCell::kValueOffset); | 1501 Node* value = LoadObjectField(property_cell, PropertyCell::kValueOffset); |
| 1492 GotoIf(WordEqual(value, TheHoleConstant()), &miss); | 1502 GotoIf(WordEqual(value, TheHoleConstant()), miss); |
| 1493 Return(value); | 1503 exit_point->Return(value); |
| 1504 } | |
| 1494 | 1505 |
| 1495 Node* handler; | 1506 void AccessorAssembler::LoadGlobalICHandler(const LoadICParameters* p, |
|
Igor Sheludko
2017/02/08 15:26:31
LoadGlobalIC_TryHandlerCase
jgruber
2017/02/09 09:23:42
Done.
| |
| 1496 Bind(&try_handler); | 1507 TypeofMode typeof_mode, |
| 1497 { | 1508 ExitPoint* exit_point, |
| 1498 handler = | 1509 Label* miss) { |
| 1499 LoadFixedArrayElement(p->vector, p->slot, kPointerSize, SMI_PARAMETERS); | 1510 Comment("LoadGlobalICHandler"); |
|
Igor Sheludko
2017/02/08 15:26:31
Same here.
jgruber
2017/02/09 09:23:42
Done.
| |
| 1500 CSA_ASSERT(this, Word32BinaryNot(TaggedIsSmi(handler))); | |
| 1501 GotoIf(WordEqual(handler, LoadRoot(Heap::kuninitialized_symbolRootIndex)), | |
| 1502 &miss); | |
| 1503 GotoIf(IsCodeMap(LoadMap(handler)), &call_handler); | |
| 1504 | 1511 |
| 1505 bool throw_reference_error_if_nonexistent = | 1512 Label call_handler(this); |
| 1506 typeof_mode == NOT_INSIDE_TYPEOF; | 1513 |
| 1507 HandleLoadGlobalICHandlerCase(p, handler, &miss, | 1514 Node* handler = |
| 1508 throw_reference_error_if_nonexistent); | 1515 LoadFixedArrayElement(p->vector, p->slot, kPointerSize, SMI_PARAMETERS); |
| 1509 } | 1516 CSA_ASSERT(this, Word32BinaryNot(TaggedIsSmi(handler))); |
| 1517 GotoIf(WordEqual(handler, LoadRoot(Heap::kuninitialized_symbolRootIndex)), | |
| 1518 miss); | |
| 1519 GotoIf(IsCodeMap(LoadMap(handler)), &call_handler); | |
| 1520 | |
| 1521 bool throw_reference_error_if_nonexistent = typeof_mode == NOT_INSIDE_TYPEOF; | |
| 1522 HandleLoadGlobalICHandlerCase(p, handler, miss, exit_point, | |
| 1523 throw_reference_error_if_nonexistent); | |
| 1510 | 1524 |
| 1511 Bind(&call_handler); | 1525 Bind(&call_handler); |
| 1512 { | 1526 { |
| 1513 LoadWithVectorDescriptor descriptor(isolate()); | 1527 LoadWithVectorDescriptor descriptor(isolate()); |
| 1514 Node* native_context = LoadNativeContext(p->context); | 1528 Node* native_context = LoadNativeContext(p->context); |
| 1515 Node* receiver = | 1529 Node* receiver = |
| 1516 LoadContextElement(native_context, Context::EXTENSION_INDEX); | 1530 LoadContextElement(native_context, Context::EXTENSION_INDEX); |
| 1517 TailCallStub(descriptor, handler, p->context, receiver, p->name, p->slot, | 1531 exit_point->ReturnStub(descriptor, handler, p->context, receiver, p->name, |
| 1518 p->vector); | 1532 p->slot, p->vector); |
| 1519 } | |
| 1520 Bind(&miss); | |
| 1521 { | |
| 1522 TailCallRuntime(Runtime::kLoadGlobalIC_Miss, p->context, p->name, p->slot, | |
| 1523 p->vector); | |
| 1524 } | 1533 } |
| 1525 } | 1534 } |
| 1526 | 1535 |
| 1536 void AccessorAssembler::LoadGlobalICMiss(const LoadICParameters* p, | |
| 1537 ExitPoint* exit_point) { | |
| 1538 Comment("LoadGlobalICMiss"); | |
| 1539 | |
| 1540 exit_point->ReturnRuntime(Runtime::kLoadGlobalIC_Miss, p->context, p->name, | |
| 1541 p->slot, p->vector); | |
| 1542 } | |
| 1543 | |
| 1544 void AccessorAssembler::LoadGlobalIC(const LoadICParameters* p, | |
| 1545 TypeofMode typeof_mode) { | |
| 1546 ExitPoint direct_exit(this); | |
| 1547 | |
| 1548 Label try_handler(this), miss(this); | |
| 1549 LoadGlobalICData(p, &direct_exit, &try_handler, &miss); | |
| 1550 | |
| 1551 Bind(&try_handler); | |
| 1552 LoadGlobalICHandler(p, typeof_mode, &direct_exit, &miss); | |
| 1553 | |
| 1554 Bind(&miss); | |
| 1555 LoadGlobalICMiss(p, &direct_exit); | |
| 1556 } | |
| 1557 | |
| 1527 void AccessorAssembler::KeyedLoadIC(const LoadICParameters* p) { | 1558 void AccessorAssembler::KeyedLoadIC(const LoadICParameters* p) { |
| 1528 Variable var_handler(this, MachineRepresentation::kTagged); | 1559 Variable var_handler(this, MachineRepresentation::kTagged); |
| 1529 // TODO(ishell): defer blocks when it works. | 1560 // TODO(ishell): defer blocks when it works. |
| 1530 Label if_handler(this, &var_handler), try_polymorphic(this), | 1561 Label if_handler(this, &var_handler), try_polymorphic(this), |
| 1531 try_megamorphic(this /*, Label::kDeferred*/), | 1562 try_megamorphic(this /*, Label::kDeferred*/), |
| 1532 try_polymorphic_name(this /*, Label::kDeferred*/), | 1563 try_polymorphic_name(this /*, Label::kDeferred*/), |
| 1533 miss(this /*, Label::kDeferred*/); | 1564 miss(this /*, Label::kDeferred*/); |
| 1534 | 1565 |
| 1535 Node* receiver_map = LoadReceiverMap(p->receiver); | 1566 Node* receiver_map = LoadReceiverMap(p->receiver); |
| 1536 | 1567 |
| (...skipping 285 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1822 void AccessorAssembler::GenerateLoadField() { | 1853 void AccessorAssembler::GenerateLoadField() { |
| 1823 typedef LoadFieldDescriptor Descriptor; | 1854 typedef LoadFieldDescriptor Descriptor; |
| 1824 | 1855 |
| 1825 Node* receiver = Parameter(Descriptor::kReceiver); | 1856 Node* receiver = Parameter(Descriptor::kReceiver); |
| 1826 Node* name = nullptr; | 1857 Node* name = nullptr; |
| 1827 Node* slot = nullptr; | 1858 Node* slot = nullptr; |
| 1828 Node* vector = nullptr; | 1859 Node* vector = nullptr; |
| 1829 Node* context = Parameter(Descriptor::kContext); | 1860 Node* context = Parameter(Descriptor::kContext); |
| 1830 LoadICParameters p(context, receiver, name, slot, vector); | 1861 LoadICParameters p(context, receiver, name, slot, vector); |
| 1831 | 1862 |
| 1863 ExitPoint direct_exit(this); | |
| 1864 | |
| 1832 HandleLoadICSmiHandlerCase(&p, receiver, Parameter(Descriptor::kSmiHandler), | 1865 HandleLoadICSmiHandlerCase(&p, receiver, Parameter(Descriptor::kSmiHandler), |
| 1833 nullptr, kOnlyProperties); | 1866 nullptr, &direct_exit, kOnlyProperties); |
| 1834 } | 1867 } |
| 1835 | 1868 |
| 1836 void AccessorAssembler::GenerateLoadGlobalIC(TypeofMode typeof_mode) { | 1869 void AccessorAssembler::GenerateLoadGlobalIC(TypeofMode typeof_mode) { |
| 1837 typedef LoadGlobalWithVectorDescriptor Descriptor; | 1870 typedef LoadGlobalWithVectorDescriptor Descriptor; |
| 1838 | 1871 |
| 1839 Node* name = Parameter(Descriptor::kName); | 1872 Node* name = Parameter(Descriptor::kName); |
| 1840 Node* slot = Parameter(Descriptor::kSlot); | 1873 Node* slot = Parameter(Descriptor::kSlot); |
| 1841 Node* vector = Parameter(Descriptor::kVector); | 1874 Node* vector = Parameter(Descriptor::kVector); |
| 1842 Node* context = Parameter(Descriptor::kContext); | 1875 Node* context = Parameter(Descriptor::kContext); |
| 1843 | 1876 |
| (...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1948 Node* slot = Parameter(Descriptor::kSlot); | 1981 Node* slot = Parameter(Descriptor::kSlot); |
| 1949 Node* context = Parameter(Descriptor::kContext); | 1982 Node* context = Parameter(Descriptor::kContext); |
| 1950 Node* vector = LoadFeedbackVectorForStub(); | 1983 Node* vector = LoadFeedbackVectorForStub(); |
| 1951 | 1984 |
| 1952 StoreICParameters p(context, receiver, name, value, slot, vector); | 1985 StoreICParameters p(context, receiver, name, value, slot, vector); |
| 1953 KeyedStoreIC(&p, language_mode); | 1986 KeyedStoreIC(&p, language_mode); |
| 1954 } | 1987 } |
| 1955 | 1988 |
| 1956 } // namespace internal | 1989 } // namespace internal |
| 1957 } // namespace v8 | 1990 } // namespace v8 |
| OLD | NEW |