1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2  * vim: set ts=8 sts=2 et sw=2 tw=80:
3  * This Source Code Form is subject to the terms of the Mozilla Public
4  * License, v. 2.0. If a copy of the MPL was not distributed with this
5  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 
7 #include "jit/KnownClass.h"
8 
9 #include "jit/MIR.h"
10 #include "vm/ArrayObject.h"
11 #include "vm/Iteration.h"
12 #include "vm/JSFunction.h"
13 #include "vm/PlainObject.h"  // js::PlainObject
14 #include "vm/RegExpObject.h"
15 
16 using namespace js;
17 using namespace js::jit;
18 
GetObjectKnownClass(const MDefinition * def)19 KnownClass jit::GetObjectKnownClass(const MDefinition* def) {
20   MOZ_ASSERT(def->type() == MIRType::Object);
21 
22   switch (def->op()) {
23     case MDefinition::Opcode::NewArray:
24     case MDefinition::Opcode::NewArrayDynamicLength:
25     case MDefinition::Opcode::NewArrayObject:
26     case MDefinition::Opcode::Rest:
27       return KnownClass::Array;
28 
29     case MDefinition::Opcode::NewObject:
30     case MDefinition::Opcode::NewPlainObject:
31     case MDefinition::Opcode::CreateThis:
32       return KnownClass::PlainObject;
33 
34     case MDefinition::Opcode::Lambda:
35     case MDefinition::Opcode::LambdaArrow:
36     case MDefinition::Opcode::FunctionWithProto:
37       return KnownClass::Function;
38 
39     case MDefinition::Opcode::RegExp:
40       return KnownClass::RegExp;
41 
42     case MDefinition::Opcode::NewIterator:
43       switch (def->toNewIterator()->type()) {
44         case MNewIterator::ArrayIterator:
45           return KnownClass::ArrayIterator;
46         case MNewIterator::StringIterator:
47           return KnownClass::StringIterator;
48         case MNewIterator::RegExpStringIterator:
49           return KnownClass::RegExpStringIterator;
50       }
51       MOZ_CRASH("unreachable");
52 
53     case MDefinition::Opcode::Phi: {
54       if (def->numOperands() == 0) {
55         return KnownClass::None;
56       }
57 
58       MDefinition* op = def->getOperand(0);
59       // Check for Phis to avoid recursion for now.
60       if (op->isPhi()) {
61         return KnownClass::None;
62       }
63 
64       KnownClass known = GetObjectKnownClass(op);
65       if (known == KnownClass::None) {
66         return KnownClass::None;
67       }
68 
69       for (size_t i = 1; i < def->numOperands(); i++) {
70         op = def->getOperand(i);
71         if (op->isPhi() || GetObjectKnownClass(op) != known) {
72           return KnownClass::None;
73         }
74       }
75 
76       return known;
77     }
78 
79     default:
80       break;
81   }
82 
83   return KnownClass::None;
84 }
85 
GetObjectKnownJSClass(const MDefinition * def)86 const JSClass* jit::GetObjectKnownJSClass(const MDefinition* def) {
87   switch (GetObjectKnownClass(def)) {
88     case KnownClass::PlainObject:
89       return &PlainObject::class_;
90     case KnownClass::Array:
91       return &ArrayObject::class_;
92     case KnownClass::Function:
93       return &FunctionClass;
94     case KnownClass::RegExp:
95       return &RegExpObject::class_;
96     case KnownClass::ArrayIterator:
97       return &ArrayIteratorObject::class_;
98     case KnownClass::StringIterator:
99       return &StringIteratorObject::class_;
100     case KnownClass::RegExpStringIterator:
101       return &RegExpStringIteratorObject::class_;
102     case KnownClass::None:
103       break;
104   }
105 
106   return nullptr;
107 }
108