| 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->ReturnCallStub(callable, p->context, p->receiver, holder, |
| 299 value); |
| 297 } | 300 } |
| 298 } | 301 } |
| 299 | 302 |
| 300 void AccessorAssembler::HandleLoadICProtoHandlerCase( | 303 void AccessorAssembler::HandleLoadICProtoHandlerCase( |
| 301 const LoadICParameters* p, Node* handler, Variable* var_holder, | 304 const LoadICParameters* p, Node* handler, Variable* var_holder, |
| 302 Variable* var_smi_handler, Label* if_smi_handler, Label* miss, | 305 Variable* var_smi_handler, Label* if_smi_handler, Label* miss, |
| 303 bool throw_reference_error_if_nonexistent) { | 306 ExitPoint* exit_point, bool throw_reference_error_if_nonexistent) { |
| 304 DCHECK_EQ(MachineRepresentation::kTagged, var_holder->rep()); | 307 DCHECK_EQ(MachineRepresentation::kTagged, var_holder->rep()); |
| 305 DCHECK_EQ(MachineRepresentation::kTagged, var_smi_handler->rep()); | 308 DCHECK_EQ(MachineRepresentation::kTagged, var_smi_handler->rep()); |
| 306 | 309 |
| 307 // IC dispatchers rely on these assumptions to be held. | 310 // IC dispatchers rely on these assumptions to be held. |
| 308 STATIC_ASSERT(FixedArray::kLengthOffset == LoadHandler::kHolderCellOffset); | 311 STATIC_ASSERT(FixedArray::kLengthOffset == LoadHandler::kHolderCellOffset); |
| 309 DCHECK_EQ(FixedArray::OffsetOfElementAt(LoadHandler::kSmiHandlerIndex), | 312 DCHECK_EQ(FixedArray::OffsetOfElementAt(LoadHandler::kSmiHandlerIndex), |
| 310 LoadHandler::kSmiHandlerOffset); | 313 LoadHandler::kSmiHandlerOffset); |
| 311 DCHECK_EQ(FixedArray::OffsetOfElementAt(LoadHandler::kValidityCellIndex), | 314 DCHECK_EQ(FixedArray::OffsetOfElementAt(LoadHandler::kValidityCellIndex), |
| 312 LoadHandler::kValidityCellOffset); | 315 LoadHandler::kValidityCellOffset); |
| 313 | 316 |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 345 LoadObjectField(handler, LoadHandler::kHolderCellOffset); | 348 LoadObjectField(handler, LoadHandler::kHolderCellOffset); |
| 346 Label array_handler(this), tuple_handler(this); | 349 Label array_handler(this), tuple_handler(this); |
| 347 Branch(TaggedIsSmi(maybe_holder_cell), &array_handler, &tuple_handler); | 350 Branch(TaggedIsSmi(maybe_holder_cell), &array_handler, &tuple_handler); |
| 348 | 351 |
| 349 Bind(&tuple_handler); | 352 Bind(&tuple_handler); |
| 350 { | 353 { |
| 351 Label load_existent(this); | 354 Label load_existent(this); |
| 352 GotoIf(WordNotEqual(maybe_holder_cell, NullConstant()), &load_existent); | 355 GotoIf(WordNotEqual(maybe_holder_cell, NullConstant()), &load_existent); |
| 353 // This is a handler for a load of a non-existent value. | 356 // This is a handler for a load of a non-existent value. |
| 354 if (throw_reference_error_if_nonexistent) { | 357 if (throw_reference_error_if_nonexistent) { |
| 355 TailCallRuntime(Runtime::kThrowReferenceError, p->context, p->name); | 358 exit_point->ReturnCallRuntime(Runtime::kThrowReferenceError, p->context, |
| 359 p->name); |
| 356 } else { | 360 } else { |
| 357 Return(UndefinedConstant()); | 361 exit_point->Return(UndefinedConstant()); |
| 358 } | 362 } |
| 359 | 363 |
| 360 Bind(&load_existent); | 364 Bind(&load_existent); |
| 361 Node* holder = LoadWeakCellValue(maybe_holder_cell); | 365 Node* holder = LoadWeakCellValue(maybe_holder_cell); |
| 362 // The |holder| is guaranteed to be alive at this point since we passed | 366 // The |holder| is guaranteed to be alive at this point since we passed |
| 363 // both the receiver map check and the validity cell check. | 367 // both the receiver map check and the validity cell check. |
| 364 CSA_ASSERT(this, WordNotEqual(holder, IntPtrConstant(0))); | 368 CSA_ASSERT(this, WordNotEqual(holder, IntPtrConstant(0))); |
| 365 | 369 |
| 366 var_holder->Bind(holder); | 370 var_holder->Bind(holder); |
| 367 var_smi_handler->Bind(smi_handler); | 371 var_smi_handler->Bind(smi_handler); |
| 368 Goto(if_smi_handler); | 372 Goto(if_smi_handler); |
| 369 } | 373 } |
| 370 | 374 |
| 371 Bind(&array_handler); | 375 Bind(&array_handler); |
| 372 { | 376 { |
| 373 TailCallStub(CodeFactory::LoadICProtoArray( | 377 exit_point->ReturnCallStub( |
| 374 isolate(), throw_reference_error_if_nonexistent), | 378 CodeFactory::LoadICProtoArray(isolate(), |
| 375 p->context, p->receiver, p->name, p->slot, p->vector, handler); | 379 throw_reference_error_if_nonexistent), |
| 380 p->context, p->receiver, p->name, p->slot, p->vector, handler); |
| 376 } | 381 } |
| 377 } | 382 } |
| 378 | 383 |
| 379 Node* AccessorAssembler::EmitLoadICProtoArrayCheck( | 384 Node* AccessorAssembler::EmitLoadICProtoArrayCheck( |
| 380 const LoadICParameters* p, Node* handler, Node* handler_length, | 385 const LoadICParameters* p, Node* handler, Node* handler_length, |
| 381 Node* handler_flags, Label* miss, | 386 Node* handler_flags, Label* miss, |
| 382 bool throw_reference_error_if_nonexistent) { | 387 bool throw_reference_error_if_nonexistent) { |
| 383 Variable start_index(this, MachineType::PointerRepresentation()); | 388 Variable start_index(this, MachineType::PointerRepresentation()); |
| 384 start_index.Bind(IntPtrConstant(LoadHandler::kFirstPrototypeIndex)); | 389 start_index.Bind(IntPtrConstant(LoadHandler::kFirstPrototypeIndex)); |
| 385 | 390 |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 433 Node* holder = LoadWeakCellValue(maybe_holder_cell); | 438 Node* holder = LoadWeakCellValue(maybe_holder_cell); |
| 434 // The |holder| is guaranteed to be alive at this point since we passed | 439 // 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 | 440 // the receiver map check, the validity cell check and the prototype chain |
| 436 // check. | 441 // check. |
| 437 CSA_ASSERT(this, WordNotEqual(holder, IntPtrConstant(0))); | 442 CSA_ASSERT(this, WordNotEqual(holder, IntPtrConstant(0))); |
| 438 return holder; | 443 return holder; |
| 439 } | 444 } |
| 440 | 445 |
| 441 void AccessorAssembler::HandleLoadGlobalICHandlerCase( | 446 void AccessorAssembler::HandleLoadGlobalICHandlerCase( |
| 442 const LoadICParameters* pp, Node* handler, Label* miss, | 447 const LoadICParameters* pp, Node* handler, Label* miss, |
| 443 bool throw_reference_error_if_nonexistent) { | 448 ExitPoint* exit_point, bool throw_reference_error_if_nonexistent) { |
| 444 LoadICParameters p = *pp; | 449 LoadICParameters p = *pp; |
| 445 DCHECK_NULL(p.receiver); | 450 DCHECK_NULL(p.receiver); |
| 446 Node* native_context = LoadNativeContext(p.context); | 451 Node* native_context = LoadNativeContext(p.context); |
| 447 p.receiver = LoadContextElement(native_context, Context::EXTENSION_INDEX); | 452 p.receiver = LoadContextElement(native_context, Context::EXTENSION_INDEX); |
| 448 | 453 |
| 449 Variable var_holder(this, MachineRepresentation::kTagged); | 454 Variable var_holder(this, MachineRepresentation::kTagged); |
| 450 Variable var_smi_handler(this, MachineRepresentation::kTagged); | 455 Variable var_smi_handler(this, MachineRepresentation::kTagged); |
| 451 Label if_smi_handler(this); | 456 Label if_smi_handler(this); |
| 452 HandleLoadICProtoHandlerCase(&p, handler, &var_holder, &var_smi_handler, | 457 HandleLoadICProtoHandlerCase(&p, handler, &var_holder, &var_smi_handler, |
| 453 &if_smi_handler, miss, | 458 &if_smi_handler, miss, exit_point, |
| 454 throw_reference_error_if_nonexistent); | 459 throw_reference_error_if_nonexistent); |
| 455 Bind(&if_smi_handler); | 460 Bind(&if_smi_handler); |
| 456 HandleLoadICSmiHandlerCase(&p, var_holder.value(), var_smi_handler.value(), | 461 HandleLoadICSmiHandlerCase(&p, var_holder.value(), var_smi_handler.value(), |
| 457 miss, kOnlyProperties); | 462 miss, exit_point, kOnlyProperties); |
| 458 } | 463 } |
| 459 | 464 |
| 460 void AccessorAssembler::HandleStoreICHandlerCase( | 465 void AccessorAssembler::HandleStoreICHandlerCase( |
| 461 const StoreICParameters* p, Node* handler, Label* miss, | 466 const StoreICParameters* p, Node* handler, Label* miss, |
| 462 ElementSupport support_elements) { | 467 ElementSupport support_elements) { |
| 463 Label if_smi_handler(this), if_nonsmi_handler(this); | 468 Label if_smi_handler(this), if_nonsmi_handler(this); |
| 464 Label if_proto_handler(this), if_element_handler(this), call_handler(this); | 469 Label if_proto_handler(this), if_element_handler(this), call_handler(this); |
| 465 | 470 |
| 466 Branch(TaggedIsSmi(handler), &if_smi_handler, &if_nonsmi_handler); | 471 Branch(TaggedIsSmi(handler), &if_smi_handler, &if_nonsmi_handler); |
| 467 | 472 |
| (...skipping 381 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 849 } | 854 } |
| 850 Bind(&if_array); | 855 Bind(&if_array); |
| 851 { | 856 { |
| 852 var_length.Bind(SmiUntag(LoadJSArrayLength(object))); | 857 var_length.Bind(SmiUntag(LoadJSArrayLength(object))); |
| 853 Goto(&length_loaded); | 858 Goto(&length_loaded); |
| 854 } | 859 } |
| 855 Bind(&length_loaded); | 860 Bind(&length_loaded); |
| 856 GotoUnless(UintPtrLessThan(intptr_index, var_length.value()), miss); | 861 GotoUnless(UintPtrLessThan(intptr_index, var_length.value()), miss); |
| 857 } | 862 } |
| 858 | 863 |
| 859 void AccessorAssembler::EmitElementLoad(Node* object, Node* elements, | 864 void AccessorAssembler::EmitElementLoad( |
| 860 Node* elements_kind, Node* intptr_index, | 865 Node* object, Node* elements, Node* elements_kind, Node* intptr_index, |
| 861 Node* is_jsarray_condition, | 866 Node* is_jsarray_condition, Label* if_hole, Label* rebox_double, |
| 862 Label* if_hole, Label* rebox_double, | 867 Variable* var_double_value, Label* unimplemented_elements_kind, |
| 863 Variable* var_double_value, | 868 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), | 869 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), | 870 if_fast_double(this), if_fast_holey_double(this), if_nonfast(this), |
| 868 if_dictionary(this); | 871 if_dictionary(this); |
| 869 GotoIf( | 872 GotoIf( |
| 870 Int32GreaterThan(elements_kind, Int32Constant(LAST_FAST_ELEMENTS_KIND)), | 873 Int32GreaterThan(elements_kind, Int32Constant(LAST_FAST_ELEMENTS_KIND)), |
| 871 &if_nonfast); | 874 &if_nonfast); |
| 872 | 875 |
| 873 EmitFastElementsBoundsCheck(object, elements, intptr_index, | 876 EmitFastElementsBoundsCheck(object, elements, intptr_index, |
| 874 is_jsarray_condition, out_of_bounds); | 877 is_jsarray_condition, out_of_bounds); |
| 875 int32_t kinds[] = {// Handled by if_fast_packed. | 878 int32_t kinds[] = {// Handled by if_fast_packed. |
| (...skipping 11 matching lines...) Expand all Loading... |
| 887 // FAST_DOUBLE_ELEMENTS | 890 // FAST_DOUBLE_ELEMENTS |
| 888 &if_fast_double, | 891 &if_fast_double, |
| 889 // FAST_HOLEY_DOUBLE_ELEMENTS | 892 // FAST_HOLEY_DOUBLE_ELEMENTS |
| 890 &if_fast_holey_double}; | 893 &if_fast_holey_double}; |
| 891 Switch(elements_kind, unimplemented_elements_kind, kinds, labels, | 894 Switch(elements_kind, unimplemented_elements_kind, kinds, labels, |
| 892 arraysize(kinds)); | 895 arraysize(kinds)); |
| 893 | 896 |
| 894 Bind(&if_fast_packed); | 897 Bind(&if_fast_packed); |
| 895 { | 898 { |
| 896 Comment("fast packed elements"); | 899 Comment("fast packed elements"); |
| 897 Return(LoadFixedArrayElement(elements, intptr_index)); | 900 exit_point->Return(LoadFixedArrayElement(elements, intptr_index)); |
| 898 } | 901 } |
| 899 | 902 |
| 900 Bind(&if_fast_holey); | 903 Bind(&if_fast_holey); |
| 901 { | 904 { |
| 902 Comment("fast holey elements"); | 905 Comment("fast holey elements"); |
| 903 Node* element = LoadFixedArrayElement(elements, intptr_index); | 906 Node* element = LoadFixedArrayElement(elements, intptr_index); |
| 904 GotoIf(WordEqual(element, TheHoleConstant()), if_hole); | 907 GotoIf(WordEqual(element, TheHoleConstant()), if_hole); |
| 905 Return(element); | 908 exit_point->Return(element); |
| 906 } | 909 } |
| 907 | 910 |
| 908 Bind(&if_fast_double); | 911 Bind(&if_fast_double); |
| 909 { | 912 { |
| 910 Comment("packed double elements"); | 913 Comment("packed double elements"); |
| 911 var_double_value->Bind(LoadFixedDoubleArrayElement(elements, intptr_index, | 914 var_double_value->Bind(LoadFixedDoubleArrayElement(elements, intptr_index, |
| 912 MachineType::Float64())); | 915 MachineType::Float64())); |
| 913 Goto(rebox_double); | 916 Goto(rebox_double); |
| 914 } | 917 } |
| 915 | 918 |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 947 // Check that the value is a data property. | 950 // Check that the value is a data property. |
| 948 Node* details_index = EntryToIndex<SeededNumberDictionary>( | 951 Node* details_index = EntryToIndex<SeededNumberDictionary>( |
| 949 var_entry.value(), SeededNumberDictionary::kEntryDetailsIndex); | 952 var_entry.value(), SeededNumberDictionary::kEntryDetailsIndex); |
| 950 Node* details = SmiToWord32(LoadFixedArrayElement(elements, details_index)); | 953 Node* details = SmiToWord32(LoadFixedArrayElement(elements, details_index)); |
| 951 Node* kind = DecodeWord32<PropertyDetails::KindField>(details); | 954 Node* kind = DecodeWord32<PropertyDetails::KindField>(details); |
| 952 // TODO(jkummerow): Support accessors without missing? | 955 // TODO(jkummerow): Support accessors without missing? |
| 953 GotoUnless(Word32Equal(kind, Int32Constant(kData)), miss); | 956 GotoUnless(Word32Equal(kind, Int32Constant(kData)), miss); |
| 954 // Finally, load the value. | 957 // Finally, load the value. |
| 955 Node* value_index = EntryToIndex<SeededNumberDictionary>( | 958 Node* value_index = EntryToIndex<SeededNumberDictionary>( |
| 956 var_entry.value(), SeededNumberDictionary::kEntryValueIndex); | 959 var_entry.value(), SeededNumberDictionary::kEntryValueIndex); |
| 957 Return(LoadFixedArrayElement(elements, value_index)); | 960 exit_point->Return(LoadFixedArrayElement(elements, value_index)); |
| 958 } | 961 } |
| 959 | 962 |
| 960 Bind(&if_typed_array); | 963 Bind(&if_typed_array); |
| 961 { | 964 { |
| 962 Comment("typed elements"); | 965 Comment("typed elements"); |
| 963 // Check if buffer has been neutered. | 966 // Check if buffer has been neutered. |
| 964 Node* buffer = LoadObjectField(object, JSArrayBufferView::kBufferOffset); | 967 Node* buffer = LoadObjectField(object, JSArrayBufferView::kBufferOffset); |
| 965 GotoIf(IsDetachedBuffer(buffer), miss); | 968 GotoIf(IsDetachedBuffer(buffer), miss); |
| 966 | 969 |
| 967 // Bounds check. | 970 // Bounds check. |
| (...skipping 25 matching lines...) Expand all Loading... |
| 993 LAST_FIXED_TYPED_ARRAY_ELEMENTS_KIND - | 996 LAST_FIXED_TYPED_ARRAY_ELEMENTS_KIND - |
| 994 FIRST_FIXED_TYPED_ARRAY_ELEMENTS_KIND + 1; | 997 FIRST_FIXED_TYPED_ARRAY_ELEMENTS_KIND + 1; |
| 995 DCHECK_EQ(kTypedElementsKindCount, arraysize(elements_kinds)); | 998 DCHECK_EQ(kTypedElementsKindCount, arraysize(elements_kinds)); |
| 996 DCHECK_EQ(kTypedElementsKindCount, arraysize(elements_kind_labels)); | 999 DCHECK_EQ(kTypedElementsKindCount, arraysize(elements_kind_labels)); |
| 997 Switch(elements_kind, miss, elements_kinds, elements_kind_labels, | 1000 Switch(elements_kind, miss, elements_kinds, elements_kind_labels, |
| 998 kTypedElementsKindCount); | 1001 kTypedElementsKindCount); |
| 999 Bind(&uint8_elements); | 1002 Bind(&uint8_elements); |
| 1000 { | 1003 { |
| 1001 Comment("UINT8_ELEMENTS"); // Handles UINT8_CLAMPED_ELEMENTS too. | 1004 Comment("UINT8_ELEMENTS"); // Handles UINT8_CLAMPED_ELEMENTS too. |
| 1002 Node* element = Load(MachineType::Uint8(), backing_store, intptr_index); | 1005 Node* element = Load(MachineType::Uint8(), backing_store, intptr_index); |
| 1003 Return(SmiFromWord32(element)); | 1006 exit_point->Return(SmiFromWord32(element)); |
| 1004 } | 1007 } |
| 1005 Bind(&int8_elements); | 1008 Bind(&int8_elements); |
| 1006 { | 1009 { |
| 1007 Comment("INT8_ELEMENTS"); | 1010 Comment("INT8_ELEMENTS"); |
| 1008 Node* element = Load(MachineType::Int8(), backing_store, intptr_index); | 1011 Node* element = Load(MachineType::Int8(), backing_store, intptr_index); |
| 1009 Return(SmiFromWord32(element)); | 1012 exit_point->Return(SmiFromWord32(element)); |
| 1010 } | 1013 } |
| 1011 Bind(&uint16_elements); | 1014 Bind(&uint16_elements); |
| 1012 { | 1015 { |
| 1013 Comment("UINT16_ELEMENTS"); | 1016 Comment("UINT16_ELEMENTS"); |
| 1014 Node* index = WordShl(intptr_index, IntPtrConstant(1)); | 1017 Node* index = WordShl(intptr_index, IntPtrConstant(1)); |
| 1015 Node* element = Load(MachineType::Uint16(), backing_store, index); | 1018 Node* element = Load(MachineType::Uint16(), backing_store, index); |
| 1016 Return(SmiFromWord32(element)); | 1019 exit_point->Return(SmiFromWord32(element)); |
| 1017 } | 1020 } |
| 1018 Bind(&int16_elements); | 1021 Bind(&int16_elements); |
| 1019 { | 1022 { |
| 1020 Comment("INT16_ELEMENTS"); | 1023 Comment("INT16_ELEMENTS"); |
| 1021 Node* index = WordShl(intptr_index, IntPtrConstant(1)); | 1024 Node* index = WordShl(intptr_index, IntPtrConstant(1)); |
| 1022 Node* element = Load(MachineType::Int16(), backing_store, index); | 1025 Node* element = Load(MachineType::Int16(), backing_store, index); |
| 1023 Return(SmiFromWord32(element)); | 1026 exit_point->Return(SmiFromWord32(element)); |
| 1024 } | 1027 } |
| 1025 Bind(&uint32_elements); | 1028 Bind(&uint32_elements); |
| 1026 { | 1029 { |
| 1027 Comment("UINT32_ELEMENTS"); | 1030 Comment("UINT32_ELEMENTS"); |
| 1028 Node* index = WordShl(intptr_index, IntPtrConstant(2)); | 1031 Node* index = WordShl(intptr_index, IntPtrConstant(2)); |
| 1029 Node* element = Load(MachineType::Uint32(), backing_store, index); | 1032 Node* element = Load(MachineType::Uint32(), backing_store, index); |
| 1030 Return(ChangeUint32ToTagged(element)); | 1033 exit_point->Return(ChangeUint32ToTagged(element)); |
| 1031 } | 1034 } |
| 1032 Bind(&int32_elements); | 1035 Bind(&int32_elements); |
| 1033 { | 1036 { |
| 1034 Comment("INT32_ELEMENTS"); | 1037 Comment("INT32_ELEMENTS"); |
| 1035 Node* index = WordShl(intptr_index, IntPtrConstant(2)); | 1038 Node* index = WordShl(intptr_index, IntPtrConstant(2)); |
| 1036 Node* element = Load(MachineType::Int32(), backing_store, index); | 1039 Node* element = Load(MachineType::Int32(), backing_store, index); |
| 1037 Return(ChangeInt32ToTagged(element)); | 1040 exit_point->Return(ChangeInt32ToTagged(element)); |
| 1038 } | 1041 } |
| 1039 Bind(&float32_elements); | 1042 Bind(&float32_elements); |
| 1040 { | 1043 { |
| 1041 Comment("FLOAT32_ELEMENTS"); | 1044 Comment("FLOAT32_ELEMENTS"); |
| 1042 Node* index = WordShl(intptr_index, IntPtrConstant(2)); | 1045 Node* index = WordShl(intptr_index, IntPtrConstant(2)); |
| 1043 Node* element = Load(MachineType::Float32(), backing_store, index); | 1046 Node* element = Load(MachineType::Float32(), backing_store, index); |
| 1044 var_double_value->Bind(ChangeFloat32ToFloat64(element)); | 1047 var_double_value->Bind(ChangeFloat32ToFloat64(element)); |
| 1045 Goto(rebox_double); | 1048 Goto(rebox_double); |
| 1046 } | 1049 } |
| 1047 Bind(&float64_elements); | 1050 Bind(&float64_elements); |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1094 Label done(this); | 1097 Label done(this); |
| 1095 NameDictionaryLookup<NameDictionary>(properties, name, miss, &var_name_index, | 1098 NameDictionaryLookup<NameDictionary>(properties, name, miss, &var_name_index, |
| 1096 &done); | 1099 &done); |
| 1097 Bind(&done); | 1100 Bind(&done); |
| 1098 } | 1101 } |
| 1099 | 1102 |
| 1100 void AccessorAssembler::GenericElementLoad(Node* receiver, Node* receiver_map, | 1103 void AccessorAssembler::GenericElementLoad(Node* receiver, Node* receiver_map, |
| 1101 Node* instance_type, Node* index, | 1104 Node* instance_type, Node* index, |
| 1102 Label* slow) { | 1105 Label* slow) { |
| 1103 Comment("integer index"); | 1106 Comment("integer index"); |
| 1107 |
| 1108 ExitPoint direct_exit(this); |
| 1109 |
| 1104 Label if_element_hole(this), if_oob(this); | 1110 Label if_element_hole(this), if_oob(this); |
| 1105 // Receivers requiring non-standard element accesses (interceptors, access | 1111 // Receivers requiring non-standard element accesses (interceptors, access |
| 1106 // checks, strings and string wrappers, proxies) are handled in the runtime. | 1112 // checks, strings and string wrappers, proxies) are handled in the runtime. |
| 1107 GotoIf(Int32LessThanOrEqual(instance_type, | 1113 GotoIf(Int32LessThanOrEqual(instance_type, |
| 1108 Int32Constant(LAST_CUSTOM_ELEMENTS_RECEIVER)), | 1114 Int32Constant(LAST_CUSTOM_ELEMENTS_RECEIVER)), |
| 1109 slow); | 1115 slow); |
| 1110 Node* elements = LoadElements(receiver); | 1116 Node* elements = LoadElements(receiver); |
| 1111 Node* elements_kind = LoadMapElementsKind(receiver_map); | 1117 Node* elements_kind = LoadMapElementsKind(receiver_map); |
| 1112 Node* is_jsarray_condition = | 1118 Node* is_jsarray_condition = |
| 1113 Word32Equal(instance_type, Int32Constant(JS_ARRAY_TYPE)); | 1119 Word32Equal(instance_type, Int32Constant(JS_ARRAY_TYPE)); |
| 1114 Variable var_double_value(this, MachineRepresentation::kFloat64); | 1120 Variable var_double_value(this, MachineRepresentation::kFloat64); |
| 1115 Label rebox_double(this, &var_double_value); | 1121 Label rebox_double(this, &var_double_value); |
| 1116 | 1122 |
| 1117 // Unimplemented elements kinds fall back to a runtime call. | 1123 // Unimplemented elements kinds fall back to a runtime call. |
| 1118 Label* unimplemented_elements_kind = slow; | 1124 Label* unimplemented_elements_kind = slow; |
| 1119 IncrementCounter(isolate()->counters()->ic_keyed_load_generic_smi(), 1); | 1125 IncrementCounter(isolate()->counters()->ic_keyed_load_generic_smi(), 1); |
| 1120 EmitElementLoad(receiver, elements, elements_kind, index, | 1126 EmitElementLoad(receiver, elements, elements_kind, index, |
| 1121 is_jsarray_condition, &if_element_hole, &rebox_double, | 1127 is_jsarray_condition, &if_element_hole, &rebox_double, |
| 1122 &var_double_value, unimplemented_elements_kind, &if_oob, | 1128 &var_double_value, unimplemented_elements_kind, &if_oob, slow, |
| 1123 slow); | 1129 &direct_exit); |
| 1124 | 1130 |
| 1125 Bind(&rebox_double); | 1131 Bind(&rebox_double); |
| 1126 Return(AllocateHeapNumberWithValue(var_double_value.value())); | 1132 Return(AllocateHeapNumberWithValue(var_double_value.value())); |
| 1127 | 1133 |
| 1128 Bind(&if_oob); | 1134 Bind(&if_oob); |
| 1129 { | 1135 { |
| 1130 Comment("out of bounds"); | 1136 Comment("out of bounds"); |
| 1131 // Negative keys can't take the fast OOB path. | 1137 // Negative keys can't take the fast OOB path. |
| 1132 GotoIf(IntPtrLessThan(index, IntPtrConstant(0)), slow); | 1138 GotoIf(IntPtrLessThan(index, IntPtrConstant(0)), slow); |
| 1133 // Positive OOB indices are effectively the same as hole loads. | 1139 // Positive OOB indices are effectively the same as hole loads. |
| (...skipping 318 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1452 } | 1458 } |
| 1453 } | 1459 } |
| 1454 | 1460 |
| 1455 void AccessorAssembler::LoadICProtoArray( | 1461 void AccessorAssembler::LoadICProtoArray( |
| 1456 const LoadICParameters* p, Node* handler, | 1462 const LoadICParameters* p, Node* handler, |
| 1457 bool throw_reference_error_if_nonexistent) { | 1463 bool throw_reference_error_if_nonexistent) { |
| 1458 Label miss(this); | 1464 Label miss(this); |
| 1459 CSA_ASSERT(this, Word32BinaryNot(TaggedIsSmi(handler))); | 1465 CSA_ASSERT(this, Word32BinaryNot(TaggedIsSmi(handler))); |
| 1460 CSA_ASSERT(this, IsFixedArrayMap(LoadMap(handler))); | 1466 CSA_ASSERT(this, IsFixedArrayMap(LoadMap(handler))); |
| 1461 | 1467 |
| 1468 ExitPoint direct_exit(this); |
| 1469 |
| 1462 Node* smi_handler = LoadObjectField(handler, LoadHandler::kSmiHandlerOffset); | 1470 Node* smi_handler = LoadObjectField(handler, LoadHandler::kSmiHandlerOffset); |
| 1463 Node* handler_flags = SmiUntag(smi_handler); | 1471 Node* handler_flags = SmiUntag(smi_handler); |
| 1464 | 1472 |
| 1465 Node* handler_length = LoadAndUntagFixedArrayBaseLength(handler); | 1473 Node* handler_length = LoadAndUntagFixedArrayBaseLength(handler); |
| 1466 | 1474 |
| 1467 Node* holder = | 1475 Node* holder = |
| 1468 EmitLoadICProtoArrayCheck(p, handler, handler_length, handler_flags, | 1476 EmitLoadICProtoArrayCheck(p, handler, handler_length, handler_flags, |
| 1469 &miss, throw_reference_error_if_nonexistent); | 1477 &miss, throw_reference_error_if_nonexistent); |
| 1470 | 1478 |
| 1471 HandleLoadICSmiHandlerCase(p, holder, smi_handler, &miss, kOnlyProperties); | 1479 HandleLoadICSmiHandlerCase(p, holder, smi_handler, &miss, &direct_exit, |
| 1480 kOnlyProperties); |
| 1472 | 1481 |
| 1473 Bind(&miss); | 1482 Bind(&miss); |
| 1474 { | 1483 { |
| 1475 TailCallRuntime(Runtime::kLoadIC_Miss, p->context, p->receiver, p->name, | 1484 TailCallRuntime(Runtime::kLoadIC_Miss, p->context, p->receiver, p->name, |
| 1476 p->slot, p->vector); | 1485 p->slot, p->vector); |
| 1477 } | 1486 } |
| 1478 } | 1487 } |
| 1479 | 1488 |
| 1480 void AccessorAssembler::LoadGlobalIC(const LoadICParameters* p, | 1489 void AccessorAssembler::LoadGlobalIC_TryPropertyCellCase( |
| 1481 TypeofMode typeof_mode) { | 1490 Node* vector, Node* slot, ExitPoint* exit_point, Label* try_handler, |
| 1482 Label try_handler(this), call_handler(this), miss(this); | 1491 Label* miss, ParameterMode slot_mode) { |
| 1483 Node* weak_cell = | 1492 Comment("LoadGlobalIC_TryPropertyCellCase"); |
| 1484 LoadFixedArrayElement(p->vector, p->slot, 0, SMI_PARAMETERS); | 1493 |
| 1494 Node* weak_cell = LoadFixedArrayElement(vector, slot, 0, slot_mode); |
| 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::LoadGlobalIC_TryHandlerCase(const LoadICParameters* p, |
| 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("LoadGlobalIC_TryHandlerCase"); |
| 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->ReturnCallStub(descriptor, handler, p->context, receiver, |
| 1518 p->vector); | 1532 p->name, 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::LoadGlobalIC_MissCase(const LoadICParameters* p, |
| 1537 ExitPoint* exit_point) { |
| 1538 Comment("LoadGlobalIC_MissCase"); |
| 1539 |
| 1540 exit_point->ReturnCallRuntime(Runtime::kLoadGlobalIC_Miss, p->context, |
| 1541 p->name, 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 LoadGlobalIC_TryPropertyCellCase(p->vector, p->slot, &direct_exit, |
| 1550 &try_handler, &miss); |
| 1551 |
| 1552 Bind(&try_handler); |
| 1553 LoadGlobalIC_TryHandlerCase(p, typeof_mode, &direct_exit, &miss); |
| 1554 |
| 1555 Bind(&miss); |
| 1556 LoadGlobalIC_MissCase(p, &direct_exit); |
| 1557 } |
| 1558 |
| 1527 void AccessorAssembler::KeyedLoadIC(const LoadICParameters* p) { | 1559 void AccessorAssembler::KeyedLoadIC(const LoadICParameters* p) { |
| 1528 Variable var_handler(this, MachineRepresentation::kTagged); | 1560 Variable var_handler(this, MachineRepresentation::kTagged); |
| 1529 // TODO(ishell): defer blocks when it works. | 1561 // TODO(ishell): defer blocks when it works. |
| 1530 Label if_handler(this, &var_handler), try_polymorphic(this), | 1562 Label if_handler(this, &var_handler), try_polymorphic(this), |
| 1531 try_megamorphic(this /*, Label::kDeferred*/), | 1563 try_megamorphic(this /*, Label::kDeferred*/), |
| 1532 try_polymorphic_name(this /*, Label::kDeferred*/), | 1564 try_polymorphic_name(this /*, Label::kDeferred*/), |
| 1533 miss(this /*, Label::kDeferred*/); | 1565 miss(this /*, Label::kDeferred*/); |
| 1534 | 1566 |
| 1535 Node* receiver_map = LoadReceiverMap(p->receiver); | 1567 Node* receiver_map = LoadReceiverMap(p->receiver); |
| 1536 | 1568 |
| (...skipping 285 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1822 void AccessorAssembler::GenerateLoadField() { | 1854 void AccessorAssembler::GenerateLoadField() { |
| 1823 typedef LoadFieldDescriptor Descriptor; | 1855 typedef LoadFieldDescriptor Descriptor; |
| 1824 | 1856 |
| 1825 Node* receiver = Parameter(Descriptor::kReceiver); | 1857 Node* receiver = Parameter(Descriptor::kReceiver); |
| 1826 Node* name = nullptr; | 1858 Node* name = nullptr; |
| 1827 Node* slot = nullptr; | 1859 Node* slot = nullptr; |
| 1828 Node* vector = nullptr; | 1860 Node* vector = nullptr; |
| 1829 Node* context = Parameter(Descriptor::kContext); | 1861 Node* context = Parameter(Descriptor::kContext); |
| 1830 LoadICParameters p(context, receiver, name, slot, vector); | 1862 LoadICParameters p(context, receiver, name, slot, vector); |
| 1831 | 1863 |
| 1864 ExitPoint direct_exit(this); |
| 1865 |
| 1832 HandleLoadICSmiHandlerCase(&p, receiver, Parameter(Descriptor::kSmiHandler), | 1866 HandleLoadICSmiHandlerCase(&p, receiver, Parameter(Descriptor::kSmiHandler), |
| 1833 nullptr, kOnlyProperties); | 1867 nullptr, &direct_exit, kOnlyProperties); |
| 1834 } | 1868 } |
| 1835 | 1869 |
| 1836 void AccessorAssembler::GenerateLoadGlobalIC(TypeofMode typeof_mode) { | 1870 void AccessorAssembler::GenerateLoadGlobalIC(TypeofMode typeof_mode) { |
| 1837 typedef LoadGlobalWithVectorDescriptor Descriptor; | 1871 typedef LoadGlobalWithVectorDescriptor Descriptor; |
| 1838 | 1872 |
| 1839 Node* name = Parameter(Descriptor::kName); | 1873 Node* name = Parameter(Descriptor::kName); |
| 1840 Node* slot = Parameter(Descriptor::kSlot); | 1874 Node* slot = Parameter(Descriptor::kSlot); |
| 1841 Node* vector = Parameter(Descriptor::kVector); | 1875 Node* vector = Parameter(Descriptor::kVector); |
| 1842 Node* context = Parameter(Descriptor::kContext); | 1876 Node* context = Parameter(Descriptor::kContext); |
| 1843 | 1877 |
| (...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1948 Node* slot = Parameter(Descriptor::kSlot); | 1982 Node* slot = Parameter(Descriptor::kSlot); |
| 1949 Node* context = Parameter(Descriptor::kContext); | 1983 Node* context = Parameter(Descriptor::kContext); |
| 1950 Node* vector = LoadFeedbackVectorForStub(); | 1984 Node* vector = LoadFeedbackVectorForStub(); |
| 1951 | 1985 |
| 1952 StoreICParameters p(context, receiver, name, value, slot, vector); | 1986 StoreICParameters p(context, receiver, name, value, slot, vector); |
| 1953 KeyedStoreIC(&p, language_mode); | 1987 KeyedStoreIC(&p, language_mode); |
| 1954 } | 1988 } |
| 1955 | 1989 |
| 1956 } // namespace internal | 1990 } // namespace internal |
| 1957 } // namespace v8 | 1991 } // namespace v8 |
| OLD | NEW |