OLD | NEW |
1 // Copyright 2015 the V8 project authors. All rights reserved. | 1 // Copyright 2015 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/compiler/js-global-specialization.h" | 5 #include "src/compiler/js-global-specialization.h" |
6 | 6 |
7 #include "src/compilation-dependencies.h" | 7 #include "src/compilation-dependencies.h" |
8 #include "src/compiler/access-builder.h" | 8 #include "src/compiler/access-builder.h" |
9 #include "src/compiler/js-graph.h" | 9 #include "src/compiler/js-graph.h" |
10 #include "src/compiler/js-operator.h" | 10 #include "src/compiler/js-operator.h" |
11 #include "src/contexts.h" | 11 #include "src/contexts.h" |
| 12 #include "src/field-index-inl.h" |
12 #include "src/lookup.h" | 13 #include "src/lookup.h" |
13 #include "src/objects-inl.h" // TODO(mstarzinger): Temporary cycle breaker! | 14 #include "src/objects-inl.h" // TODO(mstarzinger): Temporary cycle breaker! |
| 15 #include "src/type-feedback-vector.h" |
14 | 16 |
15 namespace v8 { | 17 namespace v8 { |
16 namespace internal { | 18 namespace internal { |
17 namespace compiler { | 19 namespace compiler { |
18 | 20 |
19 struct JSGlobalSpecialization::ScriptContextTableLookupResult { | 21 struct JSGlobalSpecialization::ScriptContextTableLookupResult { |
20 Handle<Context> context; | 22 Handle<Context> context; |
21 bool immutable; | 23 bool immutable; |
22 int index; | 24 int index; |
23 }; | 25 }; |
24 | 26 |
25 | 27 |
26 JSGlobalSpecialization::JSGlobalSpecialization( | 28 JSGlobalSpecialization::JSGlobalSpecialization( |
27 Editor* editor, JSGraph* jsgraph, Flags flags, | 29 Editor* editor, JSGraph* jsgraph, Flags flags, |
28 Handle<GlobalObject> global_object, CompilationDependencies* dependencies) | 30 Handle<GlobalObject> global_object, CompilationDependencies* dependencies, |
| 31 Zone* zone) |
29 : AdvancedReducer(editor), | 32 : AdvancedReducer(editor), |
30 jsgraph_(jsgraph), | 33 jsgraph_(jsgraph), |
31 flags_(flags), | 34 flags_(flags), |
32 global_object_(global_object), | 35 global_object_(global_object), |
33 dependencies_(dependencies) {} | 36 dependencies_(dependencies), |
| 37 zone_(zone) {} |
34 | 38 |
35 | 39 |
36 Reduction JSGlobalSpecialization::Reduce(Node* node) { | 40 Reduction JSGlobalSpecialization::Reduce(Node* node) { |
37 switch (node->opcode()) { | 41 switch (node->opcode()) { |
38 case IrOpcode::kJSLoadGlobal: | 42 case IrOpcode::kJSLoadGlobal: |
39 return ReduceJSLoadGlobal(node); | 43 return ReduceJSLoadGlobal(node); |
40 case IrOpcode::kJSStoreGlobal: | 44 case IrOpcode::kJSStoreGlobal: |
41 return ReduceJSStoreGlobal(node); | 45 return ReduceJSStoreGlobal(node); |
| 46 case IrOpcode::kJSLoadNamed: |
| 47 return ReduceJSLoadNamed(node); |
42 default: | 48 default: |
43 break; | 49 break; |
44 } | 50 } |
45 return NoChange(); | 51 return NoChange(); |
46 } | 52 } |
47 | 53 |
48 | 54 |
49 Reduction JSGlobalSpecialization::ReduceJSLoadGlobal(Node* node) { | 55 Reduction JSGlobalSpecialization::ReduceJSLoadGlobal(Node* node) { |
50 DCHECK_EQ(IrOpcode::kJSLoadGlobal, node->opcode()); | 56 DCHECK_EQ(IrOpcode::kJSLoadGlobal, node->opcode()); |
51 Handle<Name> name = LoadGlobalParametersOf(node->op()).name(); | 57 Handle<Name> name = LoadGlobalParametersOf(node->op()).name(); |
(...skipping 171 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
223 break; | 229 break; |
224 } | 230 } |
225 } | 231 } |
226 effect = graph()->NewNode( | 232 effect = graph()->NewNode( |
227 simplified()->StoreField(AccessBuilder::ForPropertyCellValue()), | 233 simplified()->StoreField(AccessBuilder::ForPropertyCellValue()), |
228 jsgraph()->Constant(property_cell), value, effect, control); | 234 jsgraph()->Constant(property_cell), value, effect, control); |
229 return Replace(node, value, effect, control); | 235 return Replace(node, value, effect, control); |
230 } | 236 } |
231 | 237 |
232 | 238 |
| 239 // This class encapsulates all information required to access a certain |
| 240 // object property, either on the object itself or on the prototype chain. |
| 241 class JSGlobalSpecialization::PropertyAccessInfo final { |
| 242 public: |
| 243 enum Kind { kInvalid, kData, kDataConstant }; |
| 244 |
| 245 static PropertyAccessInfo DataConstant(Type* receiver_type, |
| 246 Handle<Object> constant, |
| 247 MaybeHandle<JSObject> holder) { |
| 248 return PropertyAccessInfo(holder, constant, receiver_type); |
| 249 } |
| 250 static PropertyAccessInfo Data(Type* receiver_type, FieldIndex field_index, |
| 251 Representation field_representation, |
| 252 MaybeHandle<JSObject> holder) { |
| 253 return PropertyAccessInfo(holder, field_index, field_representation, |
| 254 receiver_type); |
| 255 } |
| 256 |
| 257 PropertyAccessInfo() : kind_(kInvalid) {} |
| 258 PropertyAccessInfo(MaybeHandle<JSObject> holder, Handle<Object> constant, |
| 259 Type* receiver_type) |
| 260 : kind_(kDataConstant), |
| 261 receiver_type_(receiver_type), |
| 262 constant_(constant), |
| 263 holder_(holder) {} |
| 264 PropertyAccessInfo(MaybeHandle<JSObject> holder, FieldIndex field_index, |
| 265 Representation field_representation, Type* receiver_type) |
| 266 : kind_(kData), |
| 267 receiver_type_(receiver_type), |
| 268 holder_(holder), |
| 269 field_index_(field_index), |
| 270 field_representation_(field_representation) {} |
| 271 |
| 272 bool IsDataConstant() const { return kind() == kDataConstant; } |
| 273 bool IsData() const { return kind() == kData; } |
| 274 |
| 275 Kind kind() const { return kind_; } |
| 276 MaybeHandle<JSObject> holder() const { return holder_; } |
| 277 Handle<Object> constant() const { return constant_; } |
| 278 FieldIndex field_index() const { return field_index_; } |
| 279 Representation field_representation() const { return field_representation_; } |
| 280 Type* receiver_type() const { return receiver_type_; } |
| 281 |
| 282 private: |
| 283 Kind kind_; |
| 284 Type* receiver_type_; |
| 285 Handle<Object> constant_; |
| 286 MaybeHandle<JSObject> holder_; |
| 287 FieldIndex field_index_; |
| 288 Representation field_representation_; |
| 289 }; |
| 290 |
| 291 |
| 292 namespace { |
| 293 |
| 294 bool CanInlinePropertyAccess(Handle<Map> map) { |
| 295 // TODO(bmeurer): Do something about the number stuff. |
| 296 if (map->instance_type() == HEAP_NUMBER_TYPE) return false; |
| 297 if (map->instance_type() < FIRST_NONSTRING_TYPE) return true; |
| 298 return map->IsJSObjectMap() && !map->is_dictionary_map() && |
| 299 !map->has_named_interceptor() && |
| 300 // TODO(verwaest): Whitelist contexts to which we have access. |
| 301 !map->is_access_check_needed(); |
| 302 } |
| 303 |
| 304 } // namespace |
| 305 |
| 306 |
| 307 bool JSGlobalSpecialization::ComputePropertyAccessInfo( |
| 308 Handle<Map> map, Handle<Name> name, PropertyAccessInfo* access_info) { |
| 309 MaybeHandle<JSObject> holder; |
| 310 Type* receiver_type = Type::Class(map, graph()->zone()); |
| 311 while (CanInlinePropertyAccess(map)) { |
| 312 // Lookup the named property on the {map}. |
| 313 Handle<DescriptorArray> descriptors(map->instance_descriptors(), isolate()); |
| 314 int const number = descriptors->SearchWithCache(*name, *map); |
| 315 if (number != DescriptorArray::kNotFound) { |
| 316 PropertyDetails const details = descriptors->GetDetails(number); |
| 317 if (details.type() == DATA_CONSTANT) { |
| 318 *access_info = PropertyAccessInfo::DataConstant( |
| 319 receiver_type, handle(descriptors->GetValue(number), isolate()), |
| 320 holder); |
| 321 return true; |
| 322 } else if (details.type() == DATA) { |
| 323 int index = descriptors->GetFieldIndex(number); |
| 324 Representation field_representation = details.representation(); |
| 325 FieldIndex field_index = FieldIndex::ForPropertyIndex( |
| 326 *map, index, field_representation.IsDouble()); |
| 327 *access_info = PropertyAccessInfo::Data(receiver_type, field_index, |
| 328 field_representation, holder); |
| 329 return true; |
| 330 } else { |
| 331 // TODO(bmeurer): Add support for accessors. |
| 332 break; |
| 333 } |
| 334 } |
| 335 |
| 336 // Don't search on the prototype chain for special indices in case of |
| 337 // integer indexed exotic objects (see ES6 section 9.4.5). |
| 338 if (map->IsJSTypedArrayMap() && name->IsString() && |
| 339 IsSpecialIndex(isolate()->unicode_cache(), String::cast(*name))) { |
| 340 break; |
| 341 } |
| 342 |
| 343 // Walk up the prototype chain. |
| 344 if (!map->prototype()->IsJSObject()) { |
| 345 // TODO(bmeurer): Handle the not found case if the prototype is null. |
| 346 break; |
| 347 } |
| 348 Handle<JSObject> map_prototype(JSObject::cast(map->prototype()), isolate()); |
| 349 if (map_prototype->map()->is_deprecated()) { |
| 350 // Try to migrate the prototype object so we don't embed the deprecated |
| 351 // map into the optimized code. |
| 352 JSObject::TryMigrateInstance(map_prototype); |
| 353 } |
| 354 map = handle(map_prototype->map(), isolate()); |
| 355 holder = map_prototype; |
| 356 } |
| 357 return false; |
| 358 } |
| 359 |
| 360 |
| 361 bool JSGlobalSpecialization::ComputePropertyAccessInfos( |
| 362 MapHandleList const& maps, Handle<Name> name, |
| 363 ZoneVector<PropertyAccessInfo>* access_infos) { |
| 364 for (Handle<Map> map : maps) { |
| 365 PropertyAccessInfo access_info; |
| 366 if (!ComputePropertyAccessInfo(map, name, &access_info)) return false; |
| 367 access_infos->push_back(access_info); |
| 368 } |
| 369 return true; |
| 370 } |
| 371 |
| 372 |
| 373 Reduction JSGlobalSpecialization::ReduceJSLoadNamed(Node* node) { |
| 374 DCHECK_EQ(IrOpcode::kJSLoadNamed, node->opcode()); |
| 375 LoadNamedParameters const p = LoadNamedParametersOf(node->op()); |
| 376 Handle<Name> name = p.name(); |
| 377 Node* receiver = NodeProperties::GetValueInput(node, 0); |
| 378 Node* frame_state = NodeProperties::GetFrameStateInput(node, 1); |
| 379 Node* effect = NodeProperties::GetEffectInput(node); |
| 380 Node* control = NodeProperties::GetControlInput(node); |
| 381 |
| 382 // Not much we can do if deoptimization support is disabled. |
| 383 if (!(flags() & kDeoptimizationEnabled)) return NoChange(); |
| 384 |
| 385 // Extract receiver maps from the LOAD_IC using the LoadICNexus. |
| 386 MapHandleList receiver_maps; |
| 387 if (!p.feedback().IsValid()) return NoChange(); |
| 388 LoadICNexus nexus(p.feedback().vector(), p.feedback().slot()); |
| 389 if (nexus.ExtractMaps(&receiver_maps) == 0) return NoChange(); |
| 390 DCHECK_LT(0, receiver_maps.length()); |
| 391 |
| 392 // Compute property access infos for the receiver maps. |
| 393 ZoneVector<PropertyAccessInfo> access_infos(zone()); |
| 394 if (!ComputePropertyAccessInfos(receiver_maps, name, &access_infos)) { |
| 395 return NoChange(); |
| 396 } |
| 397 DCHECK(!access_infos.empty()); |
| 398 |
| 399 // The final states for every polymorphic branch. We join them with |
| 400 // Merge+Phi+EffectPhi at the bottom. |
| 401 ZoneVector<Node*> values(zone()); |
| 402 ZoneVector<Node*> effects(zone()); |
| 403 ZoneVector<Node*> controls(zone()); |
| 404 |
| 405 // The list of "exiting" controls, which currently go to a single deoptimize. |
| 406 // TODO(bmeurer): Consider using an IC as fallback. |
| 407 Node* const exit_effect = effect; |
| 408 ZoneVector<Node*> exit_controls(zone()); |
| 409 |
| 410 // Ensure that {receiver} is a heap object. |
| 411 Node* check = graph()->NewNode(simplified()->ObjectIsSmi(), receiver); |
| 412 Node* branch = |
| 413 graph()->NewNode(common()->Branch(BranchHint::kFalse), check, control); |
| 414 exit_controls.push_back(graph()->NewNode(common()->IfTrue(), branch)); |
| 415 control = graph()->NewNode(common()->IfFalse(), branch); |
| 416 |
| 417 // Load the {receiver} map. The resulting effect is the dominating effect for |
| 418 // all (polymorphic) branches. |
| 419 Node* receiver_map = effect = |
| 420 graph()->NewNode(simplified()->LoadField(AccessBuilder::ForMap()), |
| 421 receiver, effect, control); |
| 422 |
| 423 // Generate code for the various different property access patterns. |
| 424 Node* fallthrough_control = control; |
| 425 for (PropertyAccessInfo const& access_info : access_infos) { |
| 426 Node* this_value = receiver; |
| 427 Node* this_effect = effect; |
| 428 Node* this_control; |
| 429 |
| 430 // Perform map check on {receiver}. |
| 431 Type* receiver_type = access_info.receiver_type(); |
| 432 if (receiver_type->Is(Type::String())) { |
| 433 // Emit an instance type check for strings. |
| 434 Node* receiver_instance_type = this_effect = graph()->NewNode( |
| 435 simplified()->LoadField(AccessBuilder::ForMapInstanceType()), |
| 436 receiver_map, this_effect, fallthrough_control); |
| 437 Node* check = |
| 438 graph()->NewNode(machine()->Uint32LessThan(), receiver_instance_type, |
| 439 jsgraph()->Uint32Constant(FIRST_NONSTRING_TYPE)); |
| 440 Node* branch = graph()->NewNode(common()->Branch(BranchHint::kTrue), |
| 441 check, fallthrough_control); |
| 442 fallthrough_control = graph()->NewNode(common()->IfFalse(), branch); |
| 443 this_control = graph()->NewNode(common()->IfTrue(), branch); |
| 444 } else { |
| 445 // Emit a (sequence of) map checks for other properties. |
| 446 ZoneVector<Node*> this_controls(zone()); |
| 447 for (auto i = access_info.receiver_type()->Classes(); !i.Done(); |
| 448 i.Advance()) { |
| 449 Handle<Map> map = i.Current(); |
| 450 Node* check = |
| 451 graph()->NewNode(simplified()->ReferenceEqual(Type::Internal()), |
| 452 receiver_map, jsgraph()->Constant(map)); |
| 453 Node* branch = graph()->NewNode(common()->Branch(BranchHint::kTrue), |
| 454 check, fallthrough_control); |
| 455 this_controls.push_back(graph()->NewNode(common()->IfTrue(), branch)); |
| 456 fallthrough_control = graph()->NewNode(common()->IfFalse(), branch); |
| 457 } |
| 458 int const this_control_count = static_cast<int>(this_controls.size()); |
| 459 this_control = |
| 460 (this_control_count == 1) |
| 461 ? this_controls.front() |
| 462 : graph()->NewNode(common()->Merge(this_control_count), |
| 463 this_control_count, &this_controls.front()); |
| 464 } |
| 465 |
| 466 // Determine actual holder and perform prototype chain checks. |
| 467 Handle<JSObject> holder; |
| 468 if (access_info.holder().ToHandle(&holder)) { |
| 469 this_value = jsgraph()->Constant(holder); |
| 470 for (auto i = access_info.receiver_type()->Classes(); !i.Done(); |
| 471 i.Advance()) { |
| 472 Handle<Map> map = i.Current(); |
| 473 PrototypeIterator j(map); |
| 474 while (true) { |
| 475 // Check that the {prototype} still has the same map. For stable |
| 476 // maps, we can add a stability dependency on the prototype map; |
| 477 // for everything else we need to perform a map check at runtime. |
| 478 Handle<JSReceiver> prototype = |
| 479 PrototypeIterator::GetCurrent<JSReceiver>(j); |
| 480 if (prototype->map()->is_stable()) { |
| 481 dependencies()->AssumeMapStable( |
| 482 handle(prototype->map(), isolate())); |
| 483 } else { |
| 484 Node* prototype_map = this_effect = graph()->NewNode( |
| 485 simplified()->LoadField(AccessBuilder::ForMap()), |
| 486 jsgraph()->Constant(prototype), this_effect, this_control); |
| 487 Node* check = graph()->NewNode( |
| 488 simplified()->ReferenceEqual(Type::Internal()), prototype_map, |
| 489 jsgraph()->Constant(handle(prototype->map(), isolate()))); |
| 490 Node* branch = graph()->NewNode(common()->Branch(BranchHint::kTrue), |
| 491 check, this_control); |
| 492 exit_controls.push_back( |
| 493 graph()->NewNode(common()->IfFalse(), branch)); |
| 494 this_control = graph()->NewNode(common()->IfTrue(), branch); |
| 495 } |
| 496 // Stop once we get to the holder. |
| 497 if (prototype.is_identical_to(holder)) break; |
| 498 j.Advance(); |
| 499 } |
| 500 } |
| 501 } |
| 502 |
| 503 // Generate the actual property access. |
| 504 if (access_info.IsDataConstant()) { |
| 505 this_value = jsgraph()->Constant(access_info.constant()); |
| 506 } else { |
| 507 // TODO(bmeurer): This is sort of adhoc, and must be refactored into some |
| 508 // common code once we also have support for stores. |
| 509 DCHECK(access_info.IsData()); |
| 510 FieldIndex const field_index = access_info.field_index(); |
| 511 Representation const field_representation = |
| 512 access_info.field_representation(); |
| 513 if (!field_index.is_inobject()) { |
| 514 this_value = this_effect = graph()->NewNode( |
| 515 simplified()->LoadField(AccessBuilder::ForJSObjectProperties()), |
| 516 this_value, this_effect, this_control); |
| 517 } |
| 518 FieldAccess field_access; |
| 519 field_access.base_is_tagged = kTaggedBase; |
| 520 field_access.offset = field_index.offset(); |
| 521 field_access.name = name; |
| 522 field_access.type = Type::Any(); |
| 523 field_access.machine_type = kMachAnyTagged; |
| 524 if (field_representation.IsSmi()) { |
| 525 field_access.type = Type::Intersect( |
| 526 Type::SignedSmall(), Type::TaggedSigned(), graph()->zone()); |
| 527 } else if (field_representation.IsDouble()) { |
| 528 if (!field_index.is_inobject() || field_index.is_hidden_field() || |
| 529 !FLAG_unbox_double_fields) { |
| 530 this_value = this_effect = |
| 531 graph()->NewNode(simplified()->LoadField(field_access), |
| 532 this_value, this_effect, this_control); |
| 533 field_access.offset = HeapNumber::kValueOffset; |
| 534 field_access.name = MaybeHandle<Name>(); |
| 535 } |
| 536 field_access.type = Type::Intersect( |
| 537 Type::Number(), Type::UntaggedFloat64(), graph()->zone()); |
| 538 field_access.machine_type = kMachFloat64; |
| 539 } else if (field_representation.IsHeapObject()) { |
| 540 field_access.type = Type::TaggedPointer(); |
| 541 } |
| 542 this_value = this_effect = |
| 543 graph()->NewNode(simplified()->LoadField(field_access), this_value, |
| 544 this_effect, this_control); |
| 545 } |
| 546 |
| 547 // Remember the final state for this property access. |
| 548 values.push_back(this_value); |
| 549 effects.push_back(this_effect); |
| 550 controls.push_back(this_control); |
| 551 } |
| 552 |
| 553 // Collect the fallthru control as final "exit" control. |
| 554 exit_controls.push_back(fallthrough_control); |
| 555 |
| 556 // TODO(bmeurer/mtrofin): Splintering cannot currently deal with deferred |
| 557 // blocks that contain only a single non-deoptimize instruction (i.e. a |
| 558 // jump). Generating a single Merge here, which joins all the deoptimizing |
| 559 // controls would generate a lot of these basic blocks, however. So this |
| 560 // is disabled for now until splintering is fixed. |
| 561 #if 0 |
| 562 // Generate the single "exit" point, where we get if either all map/instance |
| 563 // type checks failed, or one of the assumptions inside one of the cases |
| 564 // failes (i.e. failing prototype chain check). |
| 565 // TODO(bmeurer): Consider falling back to IC here if deoptimization is |
| 566 // disabled. |
| 567 int const exit_control_count = static_cast<int>(exit_controls.size()); |
| 568 Node* exit_control = |
| 569 (exit_control_count == 1) |
| 570 ? exit_controls.front() |
| 571 : graph()->NewNode(common()->Merge(exit_control_count), |
| 572 exit_control_count, &exit_controls.front()); |
| 573 Node* deoptimize = graph()->NewNode(common()->Deoptimize(), frame_state, |
| 574 exit_effect, exit_control); |
| 575 // TODO(bmeurer): This should be on the AdvancedReducer somehow. |
| 576 NodeProperties::MergeControlToEnd(graph(), common(), deoptimize); |
| 577 #else |
| 578 for (Node* const exit_control : exit_controls) { |
| 579 Node* deoptimize = graph()->NewNode(common()->Deoptimize(), frame_state, |
| 580 exit_effect, exit_control); |
| 581 // TODO(bmeurer): This should be on the AdvancedReducer somehow. |
| 582 NodeProperties::MergeControlToEnd(graph(), common(), deoptimize); |
| 583 } |
| 584 #endif |
| 585 |
| 586 // Generate the final merge point for all (polymorphic) branches. |
| 587 Node* value; |
| 588 int const control_count = static_cast<int>(controls.size()); |
| 589 if (control_count == 1) { |
| 590 value = values.front(); |
| 591 effect = effects.front(); |
| 592 control = controls.front(); |
| 593 } else { |
| 594 control = graph()->NewNode(common()->Merge(control_count), control_count, |
| 595 &controls.front()); |
| 596 values.push_back(control); |
| 597 value = graph()->NewNode(common()->Phi(kMachAnyTagged, control_count), |
| 598 control_count + 1, &values.front()); |
| 599 effects.push_back(control); |
| 600 effect = graph()->NewNode(common()->EffectPhi(control_count), |
| 601 control_count + 1, &effects.front()); |
| 602 } |
| 603 return Replace(node, value, effect, control); |
| 604 } |
| 605 |
| 606 |
233 Reduction JSGlobalSpecialization::Replace(Node* node, Handle<Object> value) { | 607 Reduction JSGlobalSpecialization::Replace(Node* node, Handle<Object> value) { |
234 // TODO(bmeurer): Move this to JSGraph::HeapConstant instead? | |
235 if (value->IsConsString()) { | |
236 value = String::Flatten(Handle<String>::cast(value), TENURED); | |
237 } | |
238 return Replace(node, jsgraph()->Constant(value)); | 608 return Replace(node, jsgraph()->Constant(value)); |
239 } | 609 } |
240 | 610 |
241 | 611 |
242 bool JSGlobalSpecialization::LookupInScriptContextTable( | 612 bool JSGlobalSpecialization::LookupInScriptContextTable( |
243 Handle<Name> name, ScriptContextTableLookupResult* result) { | 613 Handle<Name> name, ScriptContextTableLookupResult* result) { |
244 if (!name->IsString()) return false; | 614 if (!name->IsString()) return false; |
245 Handle<ScriptContextTable> script_context_table( | 615 Handle<ScriptContextTable> script_context_table( |
246 global_object()->native_context()->script_context_table()); | 616 global_object()->native_context()->script_context_table()); |
247 ScriptContextTable::LookupResult lookup_result; | 617 ScriptContextTable::LookupResult lookup_result; |
(...skipping 12 matching lines...) Expand all Loading... |
260 | 630 |
261 | 631 |
262 Graph* JSGlobalSpecialization::graph() const { return jsgraph()->graph(); } | 632 Graph* JSGlobalSpecialization::graph() const { return jsgraph()->graph(); } |
263 | 633 |
264 | 634 |
265 Isolate* JSGlobalSpecialization::isolate() const { | 635 Isolate* JSGlobalSpecialization::isolate() const { |
266 return jsgraph()->isolate(); | 636 return jsgraph()->isolate(); |
267 } | 637 } |
268 | 638 |
269 | 639 |
| 640 MachineOperatorBuilder* JSGlobalSpecialization::machine() const { |
| 641 return jsgraph()->machine(); |
| 642 } |
| 643 |
| 644 |
270 CommonOperatorBuilder* JSGlobalSpecialization::common() const { | 645 CommonOperatorBuilder* JSGlobalSpecialization::common() const { |
271 return jsgraph()->common(); | 646 return jsgraph()->common(); |
272 } | 647 } |
273 | 648 |
274 | 649 |
275 JSOperatorBuilder* JSGlobalSpecialization::javascript() const { | 650 JSOperatorBuilder* JSGlobalSpecialization::javascript() const { |
276 return jsgraph()->javascript(); | 651 return jsgraph()->javascript(); |
277 } | 652 } |
278 | 653 |
279 | 654 |
280 SimplifiedOperatorBuilder* JSGlobalSpecialization::simplified() const { | 655 SimplifiedOperatorBuilder* JSGlobalSpecialization::simplified() const { |
281 return jsgraph()->simplified(); | 656 return jsgraph()->simplified(); |
282 } | 657 } |
283 | 658 |
284 } // namespace compiler | 659 } // namespace compiler |
285 } // namespace internal | 660 } // namespace internal |
286 } // namespace v8 | 661 } // namespace v8 |
OLD | NEW |