Revision f230a1cf deps/v8/src/hydrogen.h
deps/v8/src/hydrogen.h | ||
---|---|---|
30 | 30 |
|
31 | 31 |
#include "v8.h" |
32 | 32 |
|
33 |
#include "accessors.h" |
|
33 | 34 |
#include "allocation.h" |
34 | 35 |
#include "ast.h" |
35 | 36 |
#include "compiler.h" |
... | ... | |
109 | 110 |
bool IsFinished() const { return end_ != NULL; } |
110 | 111 |
void AddPhi(HPhi* phi); |
111 | 112 |
void RemovePhi(HPhi* phi); |
112 |
void AddInstruction(HInstruction* instr); |
|
113 |
void AddInstruction(HInstruction* instr, int position);
|
|
113 | 114 |
bool Dominates(HBasicBlock* other) const; |
114 | 115 |
int LoopNestingDepth() const; |
115 | 116 |
|
... | ... | |
132 | 133 |
|
133 | 134 |
void SetJoinId(BailoutId ast_id); |
134 | 135 |
|
135 |
void Finish(HControlInstruction* last); |
|
136 |
void FinishExit(HControlInstruction* instruction); |
|
137 |
void Goto(HBasicBlock* block, |
|
138 |
FunctionState* state = NULL, |
|
139 |
bool add_simulate = true); |
|
140 |
void GotoNoSimulate(HBasicBlock* block) { |
|
141 |
Goto(block, NULL, false); |
|
142 |
} |
|
143 |
|
|
144 | 136 |
int PredecessorIndexOf(HBasicBlock* predecessor) const; |
145 | 137 |
HPhi* AddNewPhi(int merged_index); |
146 | 138 |
HSimulate* AddNewSimulate(BailoutId ast_id, |
139 |
int position, |
|
147 | 140 |
RemovableSimulate removable = FIXED_SIMULATE) { |
148 | 141 |
HSimulate* instr = CreateSimulate(ast_id, removable); |
149 |
AddInstruction(instr); |
|
142 |
AddInstruction(instr, position);
|
|
150 | 143 |
return instr; |
151 | 144 |
} |
152 | 145 |
void AssignCommonDominator(HBasicBlock* other); |
153 | 146 |
void AssignLoopSuccessorDominators(); |
154 | 147 |
|
155 |
// Add the inlined function exit sequence, adding an HLeaveInlined |
|
156 |
// instruction and updating the bailout environment. |
|
157 |
void AddLeaveInlined(HValue* return_value, FunctionState* state); |
|
158 |
|
|
159 | 148 |
// If a target block is tagged as an inline function return, all |
160 | 149 |
// predecessors should contain the inlined exit sequence: |
161 | 150 |
// |
... | ... | |
169 | 158 |
} |
170 | 159 |
HBasicBlock* inlined_entry_block() { return inlined_entry_block_; } |
171 | 160 |
|
172 |
bool IsDeoptimizing() const { return is_deoptimizing_; } |
|
173 |
void MarkAsDeoptimizing() { is_deoptimizing_ = true; } |
|
161 |
bool IsDeoptimizing() const { |
|
162 |
return end() != NULL && end()->IsDeoptimize(); |
|
163 |
} |
|
164 |
|
|
165 |
void MarkUnreachable(); |
|
166 |
bool IsUnreachable() const { return !is_reachable_; } |
|
167 |
bool IsReachable() const { return is_reachable_; } |
|
174 | 168 |
|
175 | 169 |
bool IsLoopSuccessorDominator() const { |
176 | 170 |
return dominates_loop_successors_; |
... | ... | |
185 | 179 |
void Verify(); |
186 | 180 |
#endif |
187 | 181 |
|
188 |
private:
|
|
182 |
protected:
|
|
189 | 183 |
friend class HGraphBuilder; |
190 | 184 |
|
185 |
HSimulate* CreateSimulate(BailoutId ast_id, RemovableSimulate removable); |
|
186 |
void Finish(HControlInstruction* last, int position); |
|
187 |
void FinishExit(HControlInstruction* instruction, int position); |
|
188 |
void Goto(HBasicBlock* block, |
|
189 |
int position, |
|
190 |
FunctionState* state = NULL, |
|
191 |
bool add_simulate = true); |
|
192 |
void GotoNoSimulate(HBasicBlock* block, int position) { |
|
193 |
Goto(block, position, NULL, false); |
|
194 |
} |
|
195 |
|
|
196 |
// Add the inlined function exit sequence, adding an HLeaveInlined |
|
197 |
// instruction and updating the bailout environment. |
|
198 |
void AddLeaveInlined(HValue* return_value, |
|
199 |
FunctionState* state, |
|
200 |
int position); |
|
201 |
|
|
202 |
private: |
|
191 | 203 |
void RegisterPredecessor(HBasicBlock* pred); |
192 | 204 |
void AddDominatedBlock(HBasicBlock* block); |
193 | 205 |
|
194 |
HSimulate* CreateSimulate(BailoutId ast_id, RemovableSimulate removable); |
|
195 |
|
|
196 | 206 |
int block_id_; |
197 | 207 |
HGraph* graph_; |
198 | 208 |
ZoneList<HPhi*> phis_; |
... | ... | |
214 | 224 |
// For blocks marked as inline return target: the block with HEnterInlined. |
215 | 225 |
HBasicBlock* inlined_entry_block_; |
216 | 226 |
bool is_inline_return_target_ : 1; |
217 |
bool is_deoptimizing_ : 1;
|
|
227 |
bool is_reachable_ : 1;
|
|
218 | 228 |
bool dominates_loop_successors_ : 1; |
219 | 229 |
bool is_osr_entry_ : 1; |
220 | 230 |
}; |
... | ... | |
316 | 326 |
HBasicBlock* entry_block() const { return entry_block_; } |
317 | 327 |
HEnvironment* start_environment() const { return start_environment_; } |
318 | 328 |
|
319 |
void FinalizeUniqueValueIds();
|
|
329 |
void FinalizeUniqueness();
|
|
320 | 330 |
bool ProcessArgumentsObject(); |
321 | 331 |
void OrderBlocks(); |
322 | 332 |
void AssignDominators(); |
... | ... | |
332 | 342 |
|
333 | 343 |
void CollectPhis(); |
334 | 344 |
|
335 |
void set_undefined_constant(HConstant* constant) { |
|
336 |
undefined_constant_.set(constant); |
|
337 |
} |
|
338 |
HConstant* GetConstantUndefined() const { return undefined_constant_.get(); } |
|
345 |
HConstant* GetConstantUndefined(); |
|
339 | 346 |
HConstant* GetConstant0(); |
340 | 347 |
HConstant* GetConstant1(); |
341 | 348 |
HConstant* GetConstantMinus1(); |
... | ... | |
405 | 412 |
use_optimistic_licm_ = value; |
406 | 413 |
} |
407 | 414 |
|
408 |
bool has_soft_deoptimize() { |
|
409 |
return has_soft_deoptimize_; |
|
410 |
} |
|
411 |
|
|
412 |
void set_has_soft_deoptimize(bool value) { |
|
413 |
has_soft_deoptimize_ = value; |
|
414 |
} |
|
415 |
|
|
416 | 415 |
void MarkRecursive() { |
417 | 416 |
is_recursive_ = true; |
418 | 417 |
} |
... | ... | |
458 | 457 |
bool IsInsideNoSideEffectsScope() { return no_side_effects_scope_count_ > 0; } |
459 | 458 |
|
460 | 459 |
private: |
460 |
HConstant* ReinsertConstantIfNecessary(HConstant* constant); |
|
461 | 461 |
HConstant* GetConstant(SetOncePointer<HConstant>* pointer, |
462 | 462 |
int32_t integer_value); |
463 | 463 |
|
... | ... | |
477 | 477 |
ZoneList<HValue*> values_; |
478 | 478 |
ZoneList<HPhi*>* phi_list_; |
479 | 479 |
ZoneList<HInstruction*>* uint32_instructions_; |
480 |
SetOncePointer<HConstant> undefined_constant_;
|
|
480 |
SetOncePointer<HConstant> constant_undefined_;
|
|
481 | 481 |
SetOncePointer<HConstant> constant_0_; |
482 | 482 |
SetOncePointer<HConstant> constant_1_; |
483 | 483 |
SetOncePointer<HConstant> constant_minus1_; |
... | ... | |
495 | 495 |
|
496 | 496 |
bool is_recursive_; |
497 | 497 |
bool use_optimistic_licm_; |
498 |
bool has_soft_deoptimize_; |
|
499 | 498 |
bool depends_on_empty_array_proto_elements_; |
500 | 499 |
int type_change_checksum_; |
501 | 500 |
int maximum_environment_size_; |
... | ... | |
941 | 940 |
|
942 | 941 |
class HIfContinuation V8_FINAL { |
943 | 942 |
public: |
944 |
HIfContinuation() { continuation_captured_ = false; } |
|
943 |
HIfContinuation() : continuation_captured_(false) {} |
|
944 |
HIfContinuation(HBasicBlock* true_branch, |
|
945 |
HBasicBlock* false_branch) |
|
946 |
: continuation_captured_(true), true_branch_(true_branch), |
|
947 |
false_branch_(false_branch) {} |
|
945 | 948 |
~HIfContinuation() { ASSERT(!continuation_captured_); } |
946 | 949 |
|
947 | 950 |
void Capture(HBasicBlock* true_branch, |
948 |
HBasicBlock* false_branch, |
|
949 |
int position) { |
|
951 |
HBasicBlock* false_branch) { |
|
950 | 952 |
ASSERT(!continuation_captured_); |
951 | 953 |
true_branch_ = true_branch; |
952 | 954 |
false_branch_ = false_branch; |
953 |
position_ = position; |
|
954 | 955 |
continuation_captured_ = true; |
955 | 956 |
} |
956 | 957 |
|
957 | 958 |
void Continue(HBasicBlock** true_branch, |
958 |
HBasicBlock** false_branch, |
|
959 |
int* position) { |
|
959 |
HBasicBlock** false_branch) { |
|
960 | 960 |
ASSERT(continuation_captured_); |
961 | 961 |
*true_branch = true_branch_; |
962 | 962 |
*false_branch = false_branch_; |
963 |
if (position != NULL) *position = position_; |
|
964 | 963 |
continuation_captured_ = false; |
965 | 964 |
} |
966 | 965 |
|
... | ... | |
970 | 969 |
return IsTrueReachable() || IsFalseReachable(); |
971 | 970 |
} |
972 | 971 |
|
972 |
HBasicBlock* true_branch() const { return true_branch_; } |
|
973 |
HBasicBlock* false_branch() const { return false_branch_; } |
|
974 |
|
|
975 |
private: |
|
973 | 976 |
bool continuation_captured_; |
974 | 977 |
HBasicBlock* true_branch_; |
975 | 978 |
HBasicBlock* false_branch_; |
976 |
int position_; |
|
977 | 979 |
}; |
978 | 980 |
|
979 | 981 |
|
... | ... | |
982 | 984 |
explicit HGraphBuilder(CompilationInfo* info) |
983 | 985 |
: info_(info), |
984 | 986 |
graph_(NULL), |
985 |
current_block_(NULL) {} |
|
987 |
current_block_(NULL), |
|
988 |
position_(RelocInfo::kNoPosition) {} |
|
986 | 989 |
virtual ~HGraphBuilder() {} |
987 | 990 |
|
988 | 991 |
HBasicBlock* current_block() const { return current_block_; } |
... | ... | |
1005 | 1008 |
|
1006 | 1009 |
// Adding instructions. |
1007 | 1010 |
HInstruction* AddInstruction(HInstruction* instr); |
1011 |
void FinishCurrentBlock(HControlInstruction* last); |
|
1012 |
void FinishExitCurrentBlock(HControlInstruction* instruction); |
|
1013 |
|
|
1014 |
void Goto(HBasicBlock* from, |
|
1015 |
HBasicBlock* target, |
|
1016 |
FunctionState* state = NULL, |
|
1017 |
bool add_simulate = true) { |
|
1018 |
from->Goto(target, position_, state, add_simulate); |
|
1019 |
} |
|
1020 |
void Goto(HBasicBlock* target, |
|
1021 |
FunctionState* state = NULL, |
|
1022 |
bool add_simulate = true) { |
|
1023 |
Goto(current_block(), target, state, add_simulate); |
|
1024 |
} |
|
1025 |
void GotoNoSimulate(HBasicBlock* from, HBasicBlock* target) { |
|
1026 |
Goto(from, target, NULL, false); |
|
1027 |
} |
|
1028 |
void GotoNoSimulate(HBasicBlock* target) { |
|
1029 |
Goto(target, NULL, false); |
|
1030 |
} |
|
1031 |
void AddLeaveInlined(HBasicBlock* block, |
|
1032 |
HValue* return_value, |
|
1033 |
FunctionState* state) { |
|
1034 |
block->AddLeaveInlined(return_value, state, position_); |
|
1035 |
} |
|
1036 |
void AddLeaveInlined(HValue* return_value, FunctionState* state) { |
|
1037 |
return AddLeaveInlined(current_block(), return_value, state); |
|
1038 |
} |
|
1008 | 1039 |
|
1009 | 1040 |
template<class I> |
1010 | 1041 |
HInstruction* NewUncasted() { return I::New(zone(), context()); } |
... | ... | |
1199 | 1230 |
|
1200 | 1231 |
void AddSimulate(BailoutId id, RemovableSimulate removable = FIXED_SIMULATE); |
1201 | 1232 |
|
1233 |
int position() const { return position_; } |
|
1234 |
|
|
1202 | 1235 |
protected: |
1203 | 1236 |
virtual bool BuildGraph() = 0; |
1204 | 1237 |
|
... | ... | |
1228 | 1261 |
ElementsKind to_kind, |
1229 | 1262 |
bool is_jsarray); |
1230 | 1263 |
|
1264 |
HValue* BuildNumberToString(HValue* object, Handle<Type> type); |
|
1265 |
|
|
1231 | 1266 |
HInstruction* BuildUncheckedMonomorphicElementAccess( |
1232 | 1267 |
HValue* checked_object, |
1233 | 1268 |
HValue* key, |
... | ... | |
1238 | 1273 |
LoadKeyedHoleMode load_mode, |
1239 | 1274 |
KeyedAccessStoreMode store_mode); |
1240 | 1275 |
|
1241 |
HInstruction* AddExternalArrayElementAccess( |
|
1242 |
HValue* external_elements, |
|
1243 |
HValue* checked_key, |
|
1244 |
HValue* val, |
|
1245 |
HValue* dependency, |
|
1246 |
ElementsKind elements_kind, |
|
1247 |
bool is_store); |
|
1248 |
|
|
1249 |
HInstruction* AddFastElementAccess( |
|
1276 |
HInstruction* AddElementAccess( |
|
1250 | 1277 |
HValue* elements, |
1251 | 1278 |
HValue* checked_key, |
1252 | 1279 |
HValue* val, |
1253 | 1280 |
HValue* dependency, |
1254 | 1281 |
ElementsKind elements_kind, |
1255 | 1282 |
bool is_store, |
1256 |
LoadKeyedHoleMode load_mode, |
|
1257 |
KeyedAccessStoreMode store_mode); |
|
1283 |
LoadKeyedHoleMode load_mode = NEVER_RETURN_HOLE); |
|
1258 | 1284 |
|
1259 | 1285 |
HLoadNamedField* BuildLoadNamedField(HValue* object, HObjectAccess access); |
1286 |
HInstruction* AddLoadNamedField(HValue* object, HObjectAccess access); |
|
1260 | 1287 |
HInstruction* BuildLoadStringLength(HValue* object, HValue* checked_value); |
1261 | 1288 |
HStoreNamedField* AddStoreMapConstant(HValue* object, Handle<Map>); |
1262 | 1289 |
HLoadNamedField* AddLoadElements(HValue* object); |
1290 |
|
|
1291 |
bool MatchRotateRight(HValue* left, |
|
1292 |
HValue* right, |
|
1293 |
HValue** operand, |
|
1294 |
HValue** shift_amount); |
|
1295 |
|
|
1296 |
HInstruction* BuildBinaryOperation(Token::Value op, |
|
1297 |
HValue* left, |
|
1298 |
HValue* right, |
|
1299 |
Handle<Type> left_type, |
|
1300 |
Handle<Type> right_type, |
|
1301 |
Handle<Type> result_type, |
|
1302 |
Maybe<int> fixed_right_arg, |
|
1303 |
bool binop_stub = false); |
|
1304 |
|
|
1263 | 1305 |
HLoadNamedField* AddLoadFixedArrayLength(HValue *object); |
1264 | 1306 |
|
1265 | 1307 |
HValue* AddLoadJSBuiltin(Builtins::JavaScript builtin); |
1266 | 1308 |
|
1309 |
HValue* EnforceNumberType(HValue* number, Handle<Type> expected); |
|
1267 | 1310 |
HValue* TruncateToNumber(HValue* value, Handle<Type>* expected); |
1268 | 1311 |
|
1269 |
void PushAndAdd(HInstruction* instr); |
|
1270 |
|
|
1271 | 1312 |
void FinishExitWithHardDeoptimization(const char* reason, |
1272 | 1313 |
HBasicBlock* continuation); |
1273 | 1314 |
|
1274 |
void AddIncrementCounter(StatsCounter* counter, |
|
1275 |
HValue* context); |
|
1315 |
void AddIncrementCounter(StatsCounter* counter); |
|
1276 | 1316 |
|
1277 | 1317 |
class IfBuilder V8_FINAL { |
1278 | 1318 |
public: |
1279 |
explicit IfBuilder(HGraphBuilder* builder, |
|
1280 |
int position = RelocInfo::kNoPosition); |
|
1319 |
explicit IfBuilder(HGraphBuilder* builder); |
|
1281 | 1320 |
IfBuilder(HGraphBuilder* builder, |
1282 | 1321 |
HIfContinuation* continuation); |
1283 | 1322 |
|
... | ... | |
1286 | 1325 |
} |
1287 | 1326 |
|
1288 | 1327 |
template<class Condition> |
1289 |
HInstruction* If(HValue *p) {
|
|
1290 |
HControlInstruction* compare = new(zone()) Condition(p);
|
|
1328 |
Condition* If(HValue *p) {
|
|
1329 |
Condition* compare = builder()->New<Condition>(p);
|
|
1291 | 1330 |
AddCompare(compare); |
1292 | 1331 |
return compare; |
1293 | 1332 |
} |
1294 | 1333 |
|
1295 | 1334 |
template<class Condition, class P2> |
1296 |
HInstruction* If(HValue* p1, P2 p2) {
|
|
1297 |
HControlInstruction* compare = new(zone()) Condition(p1, p2);
|
|
1335 |
Condition* If(HValue* p1, P2 p2) {
|
|
1336 |
Condition* compare = builder()->New<Condition>(p1, p2);
|
|
1298 | 1337 |
AddCompare(compare); |
1299 | 1338 |
return compare; |
1300 | 1339 |
} |
1301 | 1340 |
|
1302 | 1341 |
template<class Condition, class P2, class P3> |
1303 |
HInstruction* If(HValue* p1, P2 p2, P3 p3) {
|
|
1304 |
HControlInstruction* compare = new(zone()) Condition(p1, p2, p3);
|
|
1342 |
Condition* If(HValue* p1, P2 p2, P3 p3) {
|
|
1343 |
Condition* compare = builder()->New<Condition>(p1, p2, p3);
|
|
1305 | 1344 |
AddCompare(compare); |
1306 | 1345 |
return compare; |
1307 | 1346 |
} |
1308 | 1347 |
|
1348 |
template<class Condition> |
|
1349 |
Condition* IfNot(HValue* p) { |
|
1350 |
Condition* compare = If<Condition>(p); |
|
1351 |
compare->Not(); |
|
1352 |
return compare; |
|
1353 |
} |
|
1354 |
|
|
1309 | 1355 |
template<class Condition, class P2> |
1310 |
HInstruction* IfNot(HValue* p1, P2 p2) { |
|
1311 |
HControlInstruction* compare = new(zone()) Condition(p1, p2); |
|
1312 |
AddCompare(compare); |
|
1313 |
HBasicBlock* block0 = compare->SuccessorAt(0); |
|
1314 |
HBasicBlock* block1 = compare->SuccessorAt(1); |
|
1315 |
compare->SetSuccessorAt(0, block1); |
|
1316 |
compare->SetSuccessorAt(1, block0); |
|
1356 |
Condition* IfNot(HValue* p1, P2 p2) { |
|
1357 |
Condition* compare = If<Condition>(p1, p2); |
|
1358 |
compare->Not(); |
|
1317 | 1359 |
return compare; |
1318 | 1360 |
} |
1319 | 1361 |
|
1320 | 1362 |
template<class Condition, class P2, class P3> |
1321 |
HInstruction* IfNot(HValue* p1, P2 p2, P3 p3) { |
|
1322 |
HControlInstruction* compare = new(zone()) Condition(p1, p2, p3); |
|
1323 |
AddCompare(compare); |
|
1324 |
HBasicBlock* block0 = compare->SuccessorAt(0); |
|
1325 |
HBasicBlock* block1 = compare->SuccessorAt(1); |
|
1326 |
compare->SetSuccessorAt(0, block1); |
|
1327 |
compare->SetSuccessorAt(1, block0); |
|
1363 |
Condition* IfNot(HValue* p1, P2 p2, P3 p3) { |
|
1364 |
Condition* compare = If<Condition>(p1, p2, p3); |
|
1365 |
compare->Not(); |
|
1328 | 1366 |
return compare; |
1329 | 1367 |
} |
1330 | 1368 |
|
1331 | 1369 |
template<class Condition> |
1332 |
HInstruction* OrIf(HValue *p) {
|
|
1370 |
Condition* OrIf(HValue *p) {
|
|
1333 | 1371 |
Or(); |
1334 | 1372 |
return If<Condition>(p); |
1335 | 1373 |
} |
1336 | 1374 |
|
1337 | 1375 |
template<class Condition, class P2> |
1338 |
HInstruction* OrIf(HValue* p1, P2 p2) {
|
|
1376 |
Condition* OrIf(HValue* p1, P2 p2) {
|
|
1339 | 1377 |
Or(); |
1340 | 1378 |
return If<Condition>(p1, p2); |
1341 | 1379 |
} |
1342 | 1380 |
|
1343 | 1381 |
template<class Condition, class P2, class P3> |
1344 |
HInstruction* OrIf(HValue* p1, P2 p2, P3 p3) {
|
|
1382 |
Condition* OrIf(HValue* p1, P2 p2, P3 p3) {
|
|
1345 | 1383 |
Or(); |
1346 | 1384 |
return If<Condition>(p1, p2, p3); |
1347 | 1385 |
} |
1348 | 1386 |
|
1349 | 1387 |
template<class Condition> |
1350 |
HInstruction* AndIf(HValue *p) {
|
|
1388 |
Condition* AndIf(HValue *p) {
|
|
1351 | 1389 |
And(); |
1352 | 1390 |
return If<Condition>(p); |
1353 | 1391 |
} |
1354 | 1392 |
|
1355 | 1393 |
template<class Condition, class P2> |
1356 |
HInstruction* AndIf(HValue* p1, P2 p2) {
|
|
1394 |
Condition* AndIf(HValue* p1, P2 p2) {
|
|
1357 | 1395 |
And(); |
1358 | 1396 |
return If<Condition>(p1, p2); |
1359 | 1397 |
} |
1360 | 1398 |
|
1361 | 1399 |
template<class Condition, class P2, class P3> |
1362 |
HInstruction* AndIf(HValue* p1, P2 p2, P3 p3) {
|
|
1400 |
Condition* AndIf(HValue* p1, P2 p2, P3 p3) {
|
|
1363 | 1401 |
And(); |
1364 | 1402 |
return If<Condition>(p1, p2, p3); |
1365 | 1403 |
} |
... | ... | |
1367 | 1405 |
void Or(); |
1368 | 1406 |
void And(); |
1369 | 1407 |
|
1408 |
// Captures the current state of this IfBuilder in the specified |
|
1409 |
// continuation and ends this IfBuilder. |
|
1370 | 1410 |
void CaptureContinuation(HIfContinuation* continuation); |
1371 | 1411 |
|
1412 |
// Joins the specified continuation from this IfBuilder and ends this |
|
1413 |
// IfBuilder. This appends a Goto instruction from the true branch of |
|
1414 |
// this IfBuilder to the true branch of the continuation unless the |
|
1415 |
// true branch of this IfBuilder is already finished. And vice versa |
|
1416 |
// for the false branch. |
|
1417 |
// |
|
1418 |
// The basic idea is as follows: You have several nested IfBuilder's |
|
1419 |
// that you want to join based on two possible outcomes (i.e. success |
|
1420 |
// and failure, or whatever). You can do this easily using this method |
|
1421 |
// now, for example: |
|
1422 |
// |
|
1423 |
// HIfContinuation cont(graph()->CreateBasicBlock(), |
|
1424 |
// graph()->CreateBasicBlock()); |
|
1425 |
// ... |
|
1426 |
// IfBuilder if_whatever(this); |
|
1427 |
// if_whatever.If<Condition>(arg); |
|
1428 |
// if_whatever.Then(); |
|
1429 |
// ... |
|
1430 |
// if_whatever.Else(); |
|
1431 |
// ... |
|
1432 |
// if_whatever.JoinContinuation(&cont); |
|
1433 |
// ... |
|
1434 |
// IfBuilder if_something(this); |
|
1435 |
// if_something.If<Condition>(arg1, arg2); |
|
1436 |
// if_something.Then(); |
|
1437 |
// ... |
|
1438 |
// if_something.Else(); |
|
1439 |
// ... |
|
1440 |
// if_something.JoinContinuation(&cont); |
|
1441 |
// ... |
|
1442 |
// IfBuilder if_finally(this, &cont); |
|
1443 |
// if_finally.Then(); |
|
1444 |
// // continues after then code of if_whatever or if_something. |
|
1445 |
// ... |
|
1446 |
// if_finally.Else(); |
|
1447 |
// // continues after else code of if_whatever or if_something. |
|
1448 |
// ... |
|
1449 |
// if_finally.End(); |
|
1450 |
void JoinContinuation(HIfContinuation* continuation); |
|
1451 |
|
|
1372 | 1452 |
void Then(); |
1373 | 1453 |
void Else(); |
1374 | 1454 |
void End(); |
... | ... | |
1382 | 1462 |
void Return(HValue* value); |
1383 | 1463 |
|
1384 | 1464 |
private: |
1385 |
void AddCompare(HControlInstruction* compare);
|
|
1465 |
HControlInstruction* AddCompare(HControlInstruction* compare);
|
|
1386 | 1466 |
|
1387 |
Zone* zone() { return builder_->zone(); }
|
|
1467 |
HGraphBuilder* builder() const { return builder_; }
|
|
1388 | 1468 |
|
1389 | 1469 |
HGraphBuilder* builder_; |
1390 |
int position_; |
|
1391 | 1470 |
bool finished_ : 1; |
1392 | 1471 |
bool deopt_then_ : 1; |
1393 | 1472 |
bool deopt_else_ : 1; |
... | ... | |
1548 | 1627 |
void BuildCompareNil( |
1549 | 1628 |
HValue* value, |
1550 | 1629 |
Handle<Type> type, |
1551 |
int position, |
|
1552 | 1630 |
HIfContinuation* continuation); |
1553 | 1631 |
|
1554 | 1632 |
HValue* BuildCreateAllocationMemento(HValue* previous_object, |
... | ... | |
1563 | 1641 |
HInstruction* BuildGetNativeContext(); |
1564 | 1642 |
HInstruction* BuildGetArrayFunction(); |
1565 | 1643 |
|
1644 |
protected: |
|
1645 |
void SetSourcePosition(int position) { |
|
1646 |
ASSERT(position != RelocInfo::kNoPosition); |
|
1647 |
position_ = position; |
|
1648 |
} |
|
1649 |
|
|
1566 | 1650 |
private: |
1567 | 1651 |
HGraphBuilder(); |
1568 | 1652 |
|
... | ... | |
1572 | 1656 |
CompilationInfo* info_; |
1573 | 1657 |
HGraph* graph_; |
1574 | 1658 |
HBasicBlock* current_block_; |
1659 |
int position_; |
|
1575 | 1660 |
}; |
1576 | 1661 |
|
1577 | 1662 |
|
... | ... | |
1583 | 1668 |
if (FLAG_always_opt) return NULL; |
1584 | 1669 |
} |
1585 | 1670 |
if (current_block()->IsDeoptimizing()) return NULL; |
1586 |
HDeoptimize* instr = New<HDeoptimize>(reason, type); |
|
1587 |
AddInstruction(instr); |
|
1671 |
HBasicBlock* after_deopt_block = CreateBasicBlock( |
|
1672 |
current_block()->last_environment()); |
|
1673 |
HDeoptimize* instr = New<HDeoptimize>(reason, type, after_deopt_block); |
|
1588 | 1674 |
if (type == Deoptimizer::SOFT) { |
1589 | 1675 |
isolate()->counters()->soft_deopts_inserted()->Increment(); |
1590 |
graph()->set_has_soft_deoptimize(true); |
|
1591 | 1676 |
} |
1592 |
current_block()->MarkAsDeoptimizing(); |
|
1677 |
FinishCurrentBlock(instr); |
|
1678 |
set_current_block(after_deopt_block); |
|
1593 | 1679 |
return instr; |
1594 | 1680 |
} |
1595 | 1681 |
|
... | ... | |
1622 | 1708 |
int num_parameters = graph()->info()->num_parameters(); |
1623 | 1709 |
HValue* params = AddUncasted<HConstant>(num_parameters); |
1624 | 1710 |
HReturn* return_instruction = New<HReturn>(value, params); |
1625 |
current_block()->FinishExit(return_instruction);
|
|
1711 |
FinishExitCurrentBlock(return_instruction);
|
|
1626 | 1712 |
return return_instruction; |
1627 | 1713 |
} |
1628 | 1714 |
|
... | ... | |
1634 | 1720 |
|
1635 | 1721 |
|
1636 | 1722 |
template<> |
1723 |
inline HInstruction* HGraphBuilder::AddUncasted<HCallRuntime>( |
|
1724 |
Handle<String> name, |
|
1725 |
const Runtime::Function* c_function, |
|
1726 |
int argument_count) { |
|
1727 |
HCallRuntime* instr = New<HCallRuntime>(name, c_function, argument_count); |
|
1728 |
if (graph()->info()->IsStub()) { |
|
1729 |
// When compiling code stubs, we don't want to save all double registers |
|
1730 |
// upon entry to the stub, but instead have the call runtime instruction |
|
1731 |
// save the double registers only on-demand (in the fallback case). |
|
1732 |
instr->set_save_doubles(kSaveFPRegs); |
|
1733 |
} |
|
1734 |
AddInstruction(instr); |
|
1735 |
return instr; |
|
1736 |
} |
|
1737 |
|
|
1738 |
|
|
1739 |
template<> |
|
1637 | 1740 |
inline HInstruction* HGraphBuilder::NewUncasted<HContext>() { |
1638 | 1741 |
return HContext::New(zone()); |
1639 | 1742 |
} |
1640 | 1743 |
|
1641 | 1744 |
|
1642 |
class HOptimizedGraphBuilder V8_FINAL |
|
1643 |
: public HGraphBuilder, public AstVisitor { |
|
1745 |
class HOptimizedGraphBuilder : public HGraphBuilder, public AstVisitor { |
|
1644 | 1746 |
public: |
1645 | 1747 |
// A class encapsulating (lazily-allocated) break and continue blocks for |
1646 | 1748 |
// a breakable statement. Separated from BreakAndContinueScope so that it |
... | ... | |
1707 | 1809 |
|
1708 | 1810 |
HValue* context() { return environment()->context(); } |
1709 | 1811 |
|
1812 |
HOsrBuilder* osr() const { return osr_; } |
|
1813 |
|
|
1710 | 1814 |
void Bailout(BailoutReason reason); |
1711 | 1815 |
|
1712 | 1816 |
HBasicBlock* CreateJoin(HBasicBlock* first, |
... | ... | |
1725 | 1829 |
|
1726 | 1830 |
DEFINE_AST_VISITOR_SUBCLASS_MEMBERS(); |
1727 | 1831 |
|
1728 |
private:
|
|
1832 |
protected:
|
|
1729 | 1833 |
// Type of a member function that generates inline code for a native function. |
1730 | 1834 |
typedef void (HOptimizedGraphBuilder::*InlineFunctionGenerator) |
1731 | 1835 |
(CallRuntime* call); |
... | ... | |
1812 | 1916 |
HBasicBlock* loop_successor, |
1813 | 1917 |
HBasicBlock* break_block); |
1814 | 1918 |
|
1919 |
// Build a loop entry |
|
1920 |
HBasicBlock* BuildLoopEntry(); |
|
1921 |
|
|
1922 |
// Builds a loop entry respectful of OSR requirements |
|
1923 |
HBasicBlock* BuildLoopEntry(IterationStatement* statement); |
|
1924 |
|
|
1815 | 1925 |
HBasicBlock* JoinContinue(IterationStatement* statement, |
1816 | 1926 |
HBasicBlock* exit_block, |
1817 | 1927 |
HBasicBlock* continue_block); |
... | ... | |
1837 | 1947 |
env->Bind(index, value); |
1838 | 1948 |
if (IsEligibleForEnvironmentLivenessAnalysis(var, index, value, env)) { |
1839 | 1949 |
HEnvironmentMarker* bind = |
1840 |
new(zone()) HEnvironmentMarker(HEnvironmentMarker::BIND, index);
|
|
1841 |
AddInstruction(bind);
|
|
1950 |
Add<HEnvironmentMarker>(HEnvironmentMarker::BIND, index);
|
|
1951 |
USE(bind);
|
|
1842 | 1952 |
#ifdef DEBUG |
1843 | 1953 |
bind->set_closure(env->closure()); |
1844 | 1954 |
#endif |
1845 | 1955 |
} |
1846 | 1956 |
} |
1957 |
|
|
1847 | 1958 |
HValue* LookupAndMakeLive(Variable* var) { |
1848 | 1959 |
HEnvironment* env = environment(); |
1849 | 1960 |
int index = env->IndexFor(var); |
1850 | 1961 |
HValue* value = env->Lookup(index); |
1851 | 1962 |
if (IsEligibleForEnvironmentLivenessAnalysis(var, index, value, env)) { |
1852 | 1963 |
HEnvironmentMarker* lookup = |
1853 |
new(zone()) HEnvironmentMarker(HEnvironmentMarker::LOOKUP, index);
|
|
1854 |
AddInstruction(lookup);
|
|
1964 |
Add<HEnvironmentMarker>(HEnvironmentMarker::LOOKUP, index);
|
|
1965 |
USE(lookup);
|
|
1855 | 1966 |
#ifdef DEBUG |
1856 | 1967 |
lookup->set_closure(env->closure()); |
1857 | 1968 |
#endif |
... | ... | |
1889 | 2000 |
AST_NODE_LIST(DECLARE_VISIT) |
1890 | 2001 |
#undef DECLARE_VISIT |
1891 | 2002 |
|
2003 |
private: |
|
1892 | 2004 |
// Helpers for flow graph construction. |
1893 | 2005 |
enum GlobalPropertyAccess { |
1894 | 2006 |
kUseCell, |
... | ... | |
1940 | 2052 |
|
1941 | 2053 |
void HandleGlobalVariableAssignment(Variable* var, |
1942 | 2054 |
HValue* value, |
1943 |
int position, |
|
1944 | 2055 |
BailoutId ast_id); |
1945 | 2056 |
|
1946 | 2057 |
void HandlePropertyAssignment(Assignment* expr); |
1947 | 2058 |
void HandleCompoundAssignment(Assignment* expr); |
1948 |
void HandlePolymorphicLoadNamedField(int position,
|
|
2059 |
void HandlePolymorphicLoadNamedField(BailoutId ast_id,
|
|
1949 | 2060 |
BailoutId return_id, |
1950 | 2061 |
HValue* object, |
1951 | 2062 |
SmallMapList* types, |
1952 | 2063 |
Handle<String> name); |
1953 |
HInstruction* TryLoadPolymorphicAsMonomorphic(HValue* object, |
|
1954 |
SmallMapList* types, |
|
1955 |
Handle<String> name); |
|
1956 |
void HandlePolymorphicStoreNamedField(int position, |
|
1957 |
BailoutId assignment_id, |
|
2064 |
|
|
2065 |
class PropertyAccessInfo { |
|
2066 |
public: |
|
2067 |
PropertyAccessInfo(Isolate* isolate, Handle<Map> map, Handle<String> name) |
|
2068 |
: lookup_(isolate), |
|
2069 |
map_(map), |
|
2070 |
name_(name), |
|
2071 |
access_(HObjectAccess::ForMap()) { } |
|
2072 |
|
|
2073 |
// Checkes whether this PropertyAccessInfo can be handled as a monomorphic |
|
2074 |
// load named. It additionally fills in the fields necessary to generate the |
|
2075 |
// lookup code. |
|
2076 |
bool CanLoadMonomorphic(); |
|
2077 |
|
|
2078 |
// Checks whether all types behave uniform when loading name. If all maps |
|
2079 |
// behave the same, a single monomorphic load instruction can be emitted, |
|
2080 |
// guarded by a single map-checks instruction that whether the receiver is |
|
2081 |
// an instance of any of the types. |
|
2082 |
// This method skips the first type in types, assuming that this |
|
2083 |
// PropertyAccessInfo is built for types->first(). |
|
2084 |
bool CanLoadAsMonomorphic(SmallMapList* types); |
|
2085 |
|
|
2086 |
bool IsJSObjectFieldAccessor() { |
|
2087 |
int offset; // unused |
|
2088 |
return Accessors::IsJSObjectFieldAccessor(map_, name_, &offset); |
|
2089 |
} |
|
2090 |
|
|
2091 |
bool GetJSObjectFieldAccess(HObjectAccess* access) { |
|
2092 |
if (IsStringLength()) { |
|
2093 |
*access = HObjectAccess::ForStringLength(); |
|
2094 |
return true; |
|
2095 |
} else if (IsArrayLength()) { |
|
2096 |
*access = HObjectAccess::ForArrayLength(map_->elements_kind()); |
|
2097 |
return true; |
|
2098 |
} else { |
|
2099 |
int offset; |
|
2100 |
if (Accessors::IsJSObjectFieldAccessor(map_, name_, &offset)) { |
|
2101 |
*access = HObjectAccess::ForJSObjectOffset(offset); |
|
2102 |
return true; |
|
2103 |
} |
|
2104 |
return false; |
|
2105 |
} |
|
2106 |
} |
|
2107 |
|
|
2108 |
bool has_holder() { return !holder_.is_null(); } |
|
2109 |
|
|
2110 |
LookupResult* lookup() { return &lookup_; } |
|
2111 |
Handle<Map> map() { return map_; } |
|
2112 |
Handle<JSObject> holder() { return holder_; } |
|
2113 |
Handle<JSFunction> accessor() { return accessor_; } |
|
2114 |
Handle<Object> constant() { return constant_; } |
|
2115 |
HObjectAccess access() { return access_; } |
|
2116 |
|
|
2117 |
private: |
|
2118 |
Isolate* isolate() { return lookup_.isolate(); } |
|
2119 |
|
|
2120 |
bool IsStringLength() { |
|
2121 |
return map_->instance_type() < FIRST_NONSTRING_TYPE && |
|
2122 |
name_->Equals(isolate()->heap()->length_string()); |
|
2123 |
} |
|
2124 |
|
|
2125 |
bool IsArrayLength() { |
|
2126 |
return map_->instance_type() == JS_ARRAY_TYPE && |
|
2127 |
name_->Equals(isolate()->heap()->length_string()); |
|
2128 |
} |
|
2129 |
|
|
2130 |
bool LoadResult(Handle<Map> map); |
|
2131 |
bool LookupDescriptor(); |
|
2132 |
bool LookupInPrototypes(); |
|
2133 |
bool IsCompatibleForLoad(PropertyAccessInfo* other); |
|
2134 |
|
|
2135 |
void GeneralizeRepresentation(Representation r) { |
|
2136 |
access_ = access_.WithRepresentation( |
|
2137 |
access_.representation().generalize(r)); |
|
2138 |
} |
|
2139 |
|
|
2140 |
LookupResult lookup_; |
|
2141 |
Handle<Map> map_; |
|
2142 |
Handle<String> name_; |
|
2143 |
Handle<JSObject> holder_; |
|
2144 |
Handle<JSFunction> accessor_; |
|
2145 |
Handle<Object> constant_; |
|
2146 |
HObjectAccess access_; |
|
2147 |
}; |
|
2148 |
|
|
2149 |
HInstruction* BuildLoadMonomorphic(PropertyAccessInfo* info, |
|
2150 |
HValue* object, |
|
2151 |
HInstruction* checked_object, |
|
2152 |
BailoutId ast_id, |
|
2153 |
BailoutId return_id, |
|
2154 |
bool can_inline_accessor = true); |
|
2155 |
|
|
2156 |
void HandlePolymorphicStoreNamedField(BailoutId assignment_id, |
|
1958 | 2157 |
HValue* object, |
1959 | 2158 |
HValue* value, |
1960 | 2159 |
SmallMapList* types, |
1961 | 2160 |
Handle<String> name); |
1962 |
bool TryStorePolymorphicAsMonomorphic(int position, |
|
1963 |
BailoutId assignment_id, |
|
2161 |
bool TryStorePolymorphicAsMonomorphic(BailoutId assignment_id, |
|
1964 | 2162 |
HValue* object, |
1965 | 2163 |
HValue* value, |
1966 | 2164 |
SmallMapList* types, |
... | ... | |
2009 | 2207 |
HValue* key, |
2010 | 2208 |
HValue* val, |
2011 | 2209 |
SmallMapList* maps, |
2012 |
BailoutId ast_id, |
|
2013 |
int position, |
|
2014 | 2210 |
bool is_store, |
2015 | 2211 |
KeyedAccessStoreMode store_mode, |
2016 | 2212 |
bool* has_side_effects); |
... | ... | |
2019 | 2215 |
HValue* key, |
2020 | 2216 |
HValue* val, |
2021 | 2217 |
Expression* expr, |
2022 |
BailoutId ast_id, |
|
2023 |
int position, |
|
2024 | 2218 |
bool is_store, |
2025 | 2219 |
bool* has_side_effects); |
2026 | 2220 |
|
2027 | 2221 |
HInstruction* BuildLoadNamedGeneric(HValue* object, |
2028 | 2222 |
Handle<String> name, |
2029 | 2223 |
Property* expr); |
2030 |
HInstruction* BuildCallGetter(HValue* object, |
|
2031 |
Handle<Map> map, |
|
2032 |
Handle<JSFunction> getter, |
|
2033 |
Handle<JSObject> holder); |
|
2034 |
HInstruction* BuildLoadNamedMonomorphic(HValue* object, |
|
2035 |
Handle<String> name, |
|
2036 |
Handle<Map> map); |
|
2037 | 2224 |
|
2038 | 2225 |
HCheckMaps* AddCheckMap(HValue* object, Handle<Map> map); |
2039 | 2226 |
|
2040 | 2227 |
void BuildLoad(Property* property, |
2041 |
int position, |
|
2042 | 2228 |
BailoutId ast_id); |
2043 | 2229 |
void PushLoad(Property* property, |
2044 | 2230 |
HValue* object, |
2045 |
HValue* key, |
|
2046 |
int position); |
|
2231 |
HValue* key); |
|
2047 | 2232 |
|
2048 | 2233 |
void BuildStoreForEffect(Expression* expression, |
2049 | 2234 |
Property* prop, |
... | ... | |
2080 | 2265 |
HInstruction* BuildThisFunction(); |
2081 | 2266 |
|
2082 | 2267 |
HInstruction* BuildFastLiteral(Handle<JSObject> boilerplate_object, |
2083 |
Handle<Object> allocation_site, |
|
2084 |
AllocationSiteMode mode); |
|
2268 |
AllocationSiteContext* site_context); |
|
2085 | 2269 |
|
2086 | 2270 |
void BuildEmitObjectHeader(Handle<JSObject> boilerplate_object, |
2087 | 2271 |
HInstruction* object); |
... | ... | |
2091 | 2275 |
HInstruction* object_elements); |
2092 | 2276 |
|
2093 | 2277 |
void BuildEmitInObjectProperties(Handle<JSObject> boilerplate_object, |
2094 |
HInstruction* object); |
|
2278 |
HInstruction* object, |
|
2279 |
AllocationSiteContext* site_context); |
|
2095 | 2280 |
|
2096 | 2281 |
void BuildEmitElements(Handle<JSObject> boilerplate_object, |
2097 | 2282 |
Handle<FixedArrayBase> elements, |
2098 |
HValue* object_elements); |
|
2283 |
HValue* object_elements, |
|
2284 |
AllocationSiteContext* site_context); |
|
2099 | 2285 |
|
2100 | 2286 |
void BuildEmitFixedDoubleArray(Handle<FixedArrayBase> elements, |
2101 | 2287 |
ElementsKind kind, |
... | ... | |
2103 | 2289 |
|
2104 | 2290 |
void BuildEmitFixedArray(Handle<FixedArrayBase> elements, |
2105 | 2291 |
ElementsKind kind, |
2106 |
HValue* object_elements); |
|
2292 |
HValue* object_elements, |
|
2293 |
AllocationSiteContext* site_context); |
|
2107 | 2294 |
|
2108 | 2295 |
void AddCheckPrototypeMaps(Handle<JSObject> holder, |
2109 | 2296 |
Handle<Map> receiver_map); |
... | ... | |
2112 | 2299 |
HValue* receiver, |
2113 | 2300 |
Handle<Map> receiver_map); |
2114 | 2301 |
|
2115 |
bool MatchRotateRight(HValue* left, |
|
2116 |
HValue* right, |
|
2117 |
HValue** operand, |
|
2118 |
HValue** shift_amount); |
|
2119 |
|
|
2120 | 2302 |
// The translation state of the currently-being-translated function. |
2121 | 2303 |
FunctionState* function_state_; |
2122 | 2304 |
|
Also available in: Unified diff