|
Lines 28-37
Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp_sec1
|
| 28 |
|
28 |
|
| 29 |
#if ENABLE(FTL_JIT) |
29 |
#if ENABLE(FTL_JIT) |
| 30 |
|
30 |
|
|
|
31 |
#include "CodeBlockWithJITType.h" |
| 31 |
#include "DFGAbstractState.h" |
32 |
#include "DFGAbstractState.h" |
| 32 |
#include "FTLAbstractHeapRepository.h" |
33 |
#include "FTLAbstractHeapRepository.h" |
|
|
34 |
#include "FTLExitThunkGenerator.h" |
| 33 |
#include "FTLFormattedValue.h" |
35 |
#include "FTLFormattedValue.h" |
| 34 |
#include "FTLOutput.h" |
36 |
#include "FTLOutput.h" |
|
|
37 |
#include "FTLThunks.h" |
| 38 |
#include "FTLValueSource.h" |
| 39 |
#include "LinkBuffer.h" |
| 35 |
#include "Operations.h" |
40 |
#include "Operations.h" |
| 36 |
|
41 |
|
| 37 |
namespace JSC { namespace FTL { |
42 |
namespace JSC { namespace FTL { |
|
Lines 41-47
using namespace DFG;
Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp_sec2
|
| 41 |
// Using this instead of typeCheck() helps to reduce the load on LLVM, by creating |
46 |
// Using this instead of typeCheck() helps to reduce the load on LLVM, by creating |
| 42 |
// significantly less dead code. |
47 |
// significantly less dead code. |
| 43 |
#define FTL_TYPE_CHECK(lowValue, highValue, typesPassedThrough, failCondition) do { \ |
48 |
#define FTL_TYPE_CHECK(lowValue, highValue, typesPassedThrough, failCondition) do { \ |
| 44 |
LValue _ftc_lowValue = (lowValue); \ |
49 |
FormattedValue _ftc_lowValue = (lowValue); \ |
| 45 |
Edge _ftc_highValue = (highValue); \ |
50 |
Edge _ftc_highValue = (highValue); \ |
| 46 |
SpeculatedType _ftc_typesPassedThrough = (typesPassedThrough); \ |
51 |
SpeculatedType _ftc_typesPassedThrough = (typesPassedThrough); \ |
| 47 |
if (!m_state.needsTypeCheck(_ftc_highValue, _ftc_typesPassedThrough)) \ |
52 |
if (!m_state.needsTypeCheck(_ftc_highValue, _ftc_typesPassedThrough)) \ |
|
Lines 57-62
public:
Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp_sec3
|
| 57 |
, m_localsBoolean(OperandsLike, state.graph.m_blocks[0]->variablesAtHead) |
62 |
, m_localsBoolean(OperandsLike, state.graph.m_blocks[0]->variablesAtHead) |
| 58 |
, m_locals32(OperandsLike, state.graph.m_blocks[0]->variablesAtHead) |
63 |
, m_locals32(OperandsLike, state.graph.m_blocks[0]->variablesAtHead) |
| 59 |
, m_locals64(OperandsLike, state.graph.m_blocks[0]->variablesAtHead) |
64 |
, m_locals64(OperandsLike, state.graph.m_blocks[0]->variablesAtHead) |
|
|
65 |
, m_valueSources(OperandsLike, state.graph.m_blocks[0]->variablesAtHead) |
| 66 |
, m_lastSetOperand(std::numeric_limits<int>::max()) |
| 67 |
, m_exitThunkGenerator(state) |
| 60 |
, m_state(state.graph) |
68 |
, m_state(state.graph) |
| 61 |
{ |
69 |
{ |
| 62 |
} |
70 |
} |
|
Lines 80-93
public:
Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp_sec4
|
| 80 |
m_locals64[index] = buildAlloca(m_out.m_builder, m_out.int64); |
88 |
m_locals64[index] = buildAlloca(m_out.m_builder, m_out.int64); |
| 81 |
} |
89 |
} |
| 82 |
|
90 |
|
|
|
91 |
m_initialization = appendBasicBlock(m_ftlState.function); |
| 92 |
m_out.jump(m_initialization); |
| 93 |
m_out.appendTo(m_initialization); |
| 94 |
|
| 83 |
m_callFrame = m_out.param(0); |
95 |
m_callFrame = m_out.param(0); |
| 84 |
m_tagTypeNumber = m_out.constInt64(TagTypeNumber); |
96 |
m_tagTypeNumber = m_out.constInt64(TagTypeNumber); |
| 85 |
m_tagMask = m_out.constInt64(TagMask); |
97 |
m_tagMask = m_out.constInt64(TagMask); |
| 86 |
|
98 |
|
| 87 |
m_abortFunction = constIntToPtr( |
|
|
| 88 |
m_out.constIntPtr(abort), |
| 89 |
pointerType(functionType(m_out.voidType))); |
| 90 |
|
| 91 |
for (BlockIndex blockIndex = 0; blockIndex < m_graph.m_blocks.size(); ++blockIndex) { |
99 |
for (BlockIndex blockIndex = 0; blockIndex < m_graph.m_blocks.size(); ++blockIndex) { |
| 92 |
m_highBlock = m_graph.m_blocks[blockIndex].get(); |
100 |
m_highBlock = m_graph.m_blocks[blockIndex].get(); |
| 93 |
if (!m_highBlock) |
101 |
if (!m_highBlock) |
|
Lines 98-111
public:
Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp_sec5
|
| 98 |
|
106 |
|
| 99 |
closeOverFlushedLocalOps(); |
107 |
closeOverFlushedLocalOps(); |
| 100 |
|
108 |
|
| 101 |
m_out.appendTo(m_prologue, m_blocks.get(m_graph.m_blocks[0].get())); |
109 |
m_out.appendTo(m_initialization, m_blocks.get(m_graph.m_blocks[0].get())); |
| 102 |
|
110 |
|
| 103 |
transferAndCheckArguments(); |
111 |
transferAndCheckArguments(); |
| 104 |
|
112 |
|
| 105 |
m_out.jump(m_blocks.get(m_graph.m_blocks[0].get())); |
113 |
// Leave the initialization block hanging, since we will add to it later. |
| 106 |
|
114 |
|
| 107 |
for (BlockIndex blockIndex = 0; blockIndex < m_graph.m_blocks.size(); ++blockIndex) |
115 |
for (BlockIndex blockIndex = 0; blockIndex < m_graph.m_blocks.size(); ++blockIndex) |
| 108 |
compileBlock(blockIndex); |
116 |
compileBlock(blockIndex); |
|
|
117 |
|
| 118 |
// And now complete the initialization block. |
| 119 |
linkOSRExitsAndCompleteInitializationBlock(); |
| 109 |
|
120 |
|
| 110 |
if (verboseCompilationEnabled()) |
121 |
if (verboseCompilationEnabled()) |
| 111 |
m_ftlState.dumpState("after lowering"); |
122 |
m_ftlState.dumpState("after lowering"); |
|
Lines 151-158
private:
Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp_sec6
|
| 151 |
|
162 |
|
| 152 |
void transferAndCheckArguments() |
163 |
void transferAndCheckArguments() |
| 153 |
{ |
164 |
{ |
| 154 |
// FIXME: Set up the OSR story here. |
165 |
// While checking arguments, everything is in the stack. |
| 155 |
// https://bugs.webkit.org/show_bug.cgi?id=113623 |
166 |
for (unsigned i = m_valueSources.size(); i--;) |
|
|
167 |
m_valueSources[i] = ValueSource(ValueInJSStack); |
| 156 |
|
168 |
|
| 157 |
for (int i = 0; i < m_graph.m_codeBlock->numParameters(); ++i) { |
169 |
for (int i = 0; i < m_graph.m_codeBlock->numParameters(); ++i) { |
| 158 |
Node* node = m_graph.m_arguments[i]; |
170 |
Node* node = m_graph.m_arguments[i]; |
|
Lines 170-190
private:
Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp_sec7
|
| 170 |
if (variable->shouldUnboxIfPossible()) { |
182 |
if (variable->shouldUnboxIfPossible()) { |
| 171 |
RELEASE_ASSERT(!variable->shouldUseDoubleFormat()); |
183 |
RELEASE_ASSERT(!variable->shouldUseDoubleFormat()); |
| 172 |
|
184 |
|
| 173 |
SpeculatedType prediction = variable->prediction(); |
185 |
SpeculatedType prediction = variable->argumentAwarePrediction(); |
| 174 |
|
186 |
|
| 175 |
if (isInt32Speculation(prediction)) { |
187 |
if (isInt32Speculation(prediction)) { |
| 176 |
speculateBackward(BadType, jsValue, node, isNotInt32(jsValue)); |
188 |
speculateBackward(BadType, jsValueValue(jsValue), node, isNotInt32(jsValue)); |
| 177 |
m_out.set(unboxInt32(jsValue), m_locals32.operand(variable->local())); |
189 |
m_out.set(unboxInt32(jsValue), m_locals32.operand(variable->local())); |
| 178 |
continue; |
190 |
continue; |
| 179 |
} |
191 |
} |
| 180 |
|
192 |
|
| 181 |
if (isCellSpeculation(prediction)) { |
193 |
if (isCellSpeculation(prediction)) { |
| 182 |
speculateBackward(BadType, jsValue, node, isNotCell(jsValue)); |
194 |
speculateBackward(BadType, jsValueValue(jsValue), node, isNotCell(jsValue)); |
| 183 |
m_out.set(jsValue, m_locals64.operand(variable->local())); |
195 |
m_out.set(jsValue, m_locals64.operand(variable->local())); |
| 184 |
continue; |
196 |
continue; |
| 185 |
} |
197 |
} |
| 186 |
if (isBooleanSpeculation(prediction)) { |
198 |
if (isBooleanSpeculation(prediction)) { |
| 187 |
speculateBackward(BadType, jsValue, node, isNotBoolean(jsValue)); |
199 |
speculateBackward(BadType, jsValueValue(jsValue), node, isNotBoolean(jsValue)); |
| 188 |
m_out.set(unboxBoolean(jsValue), m_localsBoolean.operand(variable->local())); |
200 |
m_out.set(unboxBoolean(jsValue), m_localsBoolean.operand(variable->local())); |
| 189 |
continue; |
201 |
continue; |
| 190 |
} |
202 |
} |
|
Lines 216-234
private:
Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp_sec8
|
| 216 |
// make IR dumps easier to read. |
228 |
// make IR dumps easier to read. |
| 217 |
m_out.appendTo(lowBlock, m_nextLowBlock); |
229 |
m_out.appendTo(lowBlock, m_nextLowBlock); |
| 218 |
|
230 |
|
| 219 |
// FIXME: We should track the OSR situation here. |
231 |
initializeOSRExitStateForBlock(); |
| 220 |
// https://bugs.webkit.org/show_bug.cgi?id=113623 |
|
|
| 221 |
|
232 |
|
| 222 |
m_int32Values.clear(); |
233 |
m_int32Values.clear(); |
| 223 |
m_jsValueValues.clear(); |
234 |
m_jsValueValues.clear(); |
| 224 |
m_booleanValues.clear(); |
235 |
m_booleanValues.clear(); |
| 225 |
m_storageValues.clear(); |
236 |
m_storageValues.clear(); |
|
|
237 |
m_timeToLive.clear(); |
| 226 |
|
238 |
|
| 227 |
m_state.reset(); |
239 |
m_state.reset(); |
| 228 |
m_state.beginBasicBlock(m_highBlock); |
240 |
m_state.beginBasicBlock(m_highBlock); |
| 229 |
|
241 |
|
| 230 |
for (unsigned nodeIndex = 0; nodeIndex < m_highBlock->size(); ++nodeIndex) |
242 |
for (m_nodeIndex = 0; m_nodeIndex < m_highBlock->size(); ++m_nodeIndex) |
| 231 |
compileNode(nodeIndex); |
243 |
compileNode(m_nodeIndex); |
| 232 |
} |
244 |
} |
| 233 |
|
245 |
|
| 234 |
void compileNode(unsigned nodeIndex) |
246 |
void compileNode(unsigned nodeIndex) |
|
Lines 240-248
private:
Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp_sec9
|
| 240 |
|
252 |
|
| 241 |
bool shouldExecuteEffects = m_state.startExecuting(m_node); |
253 |
bool shouldExecuteEffects = m_state.startExecuting(m_node); |
| 242 |
|
254 |
|
| 243 |
if (!m_node->shouldGenerate()) |
|
|
| 244 |
return; // FIXME: Implement OSR magic here. https://bugs.webkit.org/show_bug.cgi?id=113623 |
| 245 |
|
| 246 |
m_direction = (m_node->flags() & NodeExitsForward) ? ForwardSpeculation : BackwardSpeculation; |
255 |
m_direction = (m_node->flags() & NodeExitsForward) ? ForwardSpeculation : BackwardSpeculation; |
| 247 |
|
256 |
|
| 248 |
switch (m_node->op()) { |
257 |
switch (m_node->op()) { |
|
Lines 258-263
private:
Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp_sec10
|
| 258 |
case SetLocal: |
267 |
case SetLocal: |
| 259 |
compileSetLocal(); |
268 |
compileSetLocal(); |
| 260 |
break; |
269 |
break; |
|
|
270 |
case MovHint: |
| 271 |
compileMovHint(); |
| 272 |
break; |
| 273 |
case ZombieHint: |
| 274 |
compileZombieHint(); |
| 275 |
break; |
| 261 |
case MovHintAndCheck: |
276 |
case MovHintAndCheck: |
| 262 |
compileMovHintAndCheck(); |
277 |
compileMovHintAndCheck(); |
| 263 |
break; |
278 |
break; |
|
Lines 352-357
private:
Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp_sec11
|
| 352 |
break; |
367 |
break; |
| 353 |
} |
368 |
} |
| 354 |
|
369 |
|
|
|
370 |
DFG_NODE_DO_TO_CHILDREN(m_graph, m_node, use); |
| 371 |
|
| 372 |
if (m_node->hasResult()) |
| 373 |
m_timeToLive.add(m_node, m_node->adjustedRefCount()); |
| 374 |
|
| 355 |
if (shouldExecuteEffects) |
375 |
if (shouldExecuteEffects) |
| 356 |
m_state.executeEffects(nodeIndex); |
376 |
m_state.executeEffects(nodeIndex); |
| 357 |
} |
377 |
} |
|
Lines 368-375
private:
Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp_sec12
|
| 368 |
|
388 |
|
| 369 |
void compileGetLocal() |
389 |
void compileGetLocal() |
| 370 |
{ |
390 |
{ |
|
|
391 |
// GetLocal is one of the few nodes that may be left behind, with !shouldGenerate(). |
| 392 |
if (!m_node->shouldGenerate()) |
| 393 |
return; |
| 394 |
|
| 371 |
VariableAccessData* variable = m_node->variableAccessData(); |
395 |
VariableAccessData* variable = m_node->variableAccessData(); |
| 372 |
SpeculatedType prediction = variable->prediction(); |
396 |
SpeculatedType prediction = variable->argumentAwarePrediction(); |
| 373 |
AbstractValue& value = m_state.variables().operand(variable->local()); |
397 |
AbstractValue& value = m_state.variables().operand(variable->local()); |
| 374 |
|
398 |
|
| 375 |
if (prediction == SpecNone) { |
399 |
if (prediction == SpecNone) { |
|
Lines 420-432
private:
Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp_sec13
|
| 420 |
|
444 |
|
| 421 |
void compileSetLocal() |
445 |
void compileSetLocal() |
| 422 |
{ |
446 |
{ |
|
|
447 |
observeMovHint(m_node); |
| 448 |
|
| 423 |
VariableAccessData* variable = m_node->variableAccessData(); |
449 |
VariableAccessData* variable = m_node->variableAccessData(); |
| 424 |
SpeculatedType prediction = variable->prediction(); |
450 |
SpeculatedType prediction = variable->argumentAwarePrediction(); |
| 425 |
bool needsFlushing = m_flushedLocalOps.contains(m_node); |
451 |
bool needsFlushing = m_flushedLocalOps.contains(m_node); |
| 426 |
|
452 |
|
| 427 |
// FIXME: Handle the MovHint for OSR. |
|
|
| 428 |
// https://bugs.webkit.org/show_bug.cgi?id=113623 |
| 429 |
|
| 430 |
if (variable->shouldUnboxIfPossible()) { |
453 |
if (variable->shouldUnboxIfPossible()) { |
| 431 |
if (variable->shouldUseDoubleFormat()) { |
454 |
if (variable->shouldUseDoubleFormat()) { |
| 432 |
// FIXME: implement doubles in FTL. |
455 |
// FIXME: implement doubles in FTL. |
|
Lines 438-458
private:
Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp_sec14
|
| 438 |
if (isInt32Speculation(prediction)) { |
461 |
if (isInt32Speculation(prediction)) { |
| 439 |
LValue value = lowInt32(m_node->child1()); |
462 |
LValue value = lowInt32(m_node->child1()); |
| 440 |
m_out.set(value, m_locals32.operand(variable->local())); |
463 |
m_out.set(value, m_locals32.operand(variable->local())); |
| 441 |
if (needsFlushing) |
464 |
if (needsFlushing) { |
| 442 |
m_out.store32(value, payloadFor(variable->local())); |
465 |
m_out.store32(value, payloadFor(variable->local())); |
|
|
466 |
m_valueSources[variable->local()] = ValueSource(Int32InJSStack); |
| 467 |
} |
| 443 |
return; |
468 |
return; |
| 444 |
} |
469 |
} |
| 445 |
if (isCellSpeculation(prediction)) { |
470 |
if (isCellSpeculation(prediction)) { |
| 446 |
LValue value = lowCell(m_node->child1()); |
471 |
LValue value = lowCell(m_node->child1()); |
| 447 |
m_out.set(value, m_locals64.operand(variable->local())); |
472 |
m_out.set(value, m_locals64.operand(variable->local())); |
| 448 |
if (needsFlushing) |
473 |
if (needsFlushing) { |
| 449 |
m_out.store64(value, addressFor(variable->local())); |
474 |
m_out.store64(value, addressFor(variable->local())); |
|
|
475 |
m_valueSources[variable->local()] = ValueSource(ValueInJSStack); |
| 476 |
} |
| 450 |
return; |
477 |
return; |
| 451 |
} |
478 |
} |
| 452 |
if (isBooleanSpeculation(prediction)) { |
479 |
if (isBooleanSpeculation(prediction)) { |
| 453 |
m_out.set(lowBoolean(m_node->child1()), m_localsBoolean.operand(variable->local())); |
480 |
m_out.set(lowBoolean(m_node->child1()), m_localsBoolean.operand(variable->local())); |
| 454 |
if (needsFlushing) |
481 |
if (needsFlushing) { |
| 455 |
m_out.store64(lowJSValue(m_node->child1()), addressFor(variable->local())); |
482 |
m_out.store64(lowJSValue(m_node->child1()), addressFor(variable->local())); |
|
|
483 |
m_valueSources[variable->local()] = ValueSource(ValueInJSStack); |
| 484 |
} |
| 456 |
return; |
485 |
return; |
| 457 |
} |
486 |
} |
| 458 |
} |
487 |
} |
|
Lines 460-477
private:
Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp_sec15
|
| 460 |
LValue value = lowJSValue(m_node->child1()); |
489 |
LValue value = lowJSValue(m_node->child1()); |
| 461 |
if (variable->isCaptured()) { |
490 |
if (variable->isCaptured()) { |
| 462 |
m_out.store64(value, addressFor(variable->local())); |
491 |
m_out.store64(value, addressFor(variable->local())); |
|
|
492 |
m_valueSources[variable->local()] = ValueSource(ValueInJSStack); |
| 463 |
return; |
493 |
return; |
| 464 |
} |
494 |
} |
| 465 |
|
495 |
|
| 466 |
m_out.set(value, m_locals64.operand(variable->local())); |
496 |
m_out.set(value, m_locals64.operand(variable->local())); |
| 467 |
if (needsFlushing) |
497 |
if (needsFlushing) { |
| 468 |
m_out.store64(value, addressFor(variable->local())); |
498 |
m_out.store64(value, addressFor(variable->local())); |
|
|
499 |
m_valueSources[variable->local()] = ValueSource(ValueInJSStack); |
| 500 |
} |
| 501 |
} |
| 502 |
|
| 503 |
void compileMovHint() |
| 504 |
{ |
| 505 |
observeMovHint(m_node); |
| 506 |
} |
| 507 |
|
| 508 |
void compileZombieHint() |
| 509 |
{ |
| 510 |
VariableAccessData* data = m_node->variableAccessData(); |
| 511 |
m_lastSetOperand = data->local(); |
| 512 |
m_valueSources[data->local()] = ValueSource(SourceIsDead); |
| 469 |
} |
513 |
} |
| 470 |
|
514 |
|
| 471 |
void compileMovHintAndCheck() |
515 |
void compileMovHintAndCheck() |
| 472 |
{ |
516 |
{ |
| 473 |
// FIXME: Handle the MovHint for OSR. |
517 |
observeMovHint(m_node); |
| 474 |
// https://bugs.webkit.org/show_bug.cgi?id=113623 |
|
|
| 475 |
speculate(m_node->child1()); |
518 |
speculate(m_node->child1()); |
| 476 |
} |
519 |
} |
| 477 |
|
520 |
|
|
Lines 500-506
private:
Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp_sec16
|
| 500 |
} |
543 |
} |
| 501 |
|
544 |
|
| 502 |
LValue result = m_out.addWithOverflow32(left, right); |
545 |
LValue result = m_out.addWithOverflow32(left, right); |
| 503 |
speculate(Overflow, 0, 0, m_out.extractValue(result, 1)); |
546 |
speculate(Overflow, noValue(), 0, m_out.extractValue(result, 1)); |
| 504 |
m_int32Values.add(m_node, m_out.extractValue(result, 0)); |
547 |
m_int32Values.add(m_node, m_out.extractValue(result, 0)); |
| 505 |
break; |
548 |
break; |
| 506 |
} |
549 |
} |
|
Lines 524-530
private:
Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp_sec17
|
| 524 |
} |
567 |
} |
| 525 |
|
568 |
|
| 526 |
LValue result = m_out.subWithOverflow32(left, right); |
569 |
LValue result = m_out.subWithOverflow32(left, right); |
| 527 |
speculate(Overflow, 0, 0, m_out.extractValue(result, 1)); |
570 |
speculate(Overflow, noValue(), 0, m_out.extractValue(result, 1)); |
| 528 |
m_int32Values.add(m_node, m_out.extractValue(result, 0)); |
571 |
m_int32Values.add(m_node, m_out.extractValue(result, 0)); |
| 529 |
break; |
572 |
break; |
| 530 |
} |
573 |
} |
|
Lines 547-553
private:
Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp_sec18
|
| 547 |
result = m_out.mul(left, right); |
590 |
result = m_out.mul(left, right); |
| 548 |
else { |
591 |
else { |
| 549 |
LValue overflowResult = m_out.mulWithOverflow32(left, right); |
592 |
LValue overflowResult = m_out.mulWithOverflow32(left, right); |
| 550 |
speculate(Overflow, 0, 0, m_out.extractValue(overflowResult, 1)); |
593 |
speculate(Overflow, noValue(), 0, m_out.extractValue(overflowResult, 1)); |
| 551 |
result = m_out.extractValue(overflowResult, 0); |
594 |
result = m_out.extractValue(overflowResult, 0); |
| 552 |
} |
595 |
} |
| 553 |
|
596 |
|
|
Lines 556-563
private:
Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp_sec19
|
| 556 |
LBasicBlock continuation = m_out.newBlock(); |
599 |
LBasicBlock continuation = m_out.newBlock(); |
| 557 |
|
600 |
|
| 558 |
LBasicBlock lastNext = m_out.appendTo(slowCase, continuation); |
601 |
LBasicBlock lastNext = m_out.appendTo(slowCase, continuation); |
| 559 |
speculate(NegativeZero, 0, 0, m_out.lessThan(left, m_out.int32Zero)); |
602 |
speculate(NegativeZero, noValue(), 0, m_out.lessThan(left, m_out.int32Zero)); |
| 560 |
speculate(NegativeZero, 0, 0, m_out.lessThan(right, m_out.int32Zero)); |
603 |
speculate(NegativeZero, noValue(), 0, m_out.lessThan(right, m_out.int32Zero)); |
| 561 |
m_out.jump(continuation); |
604 |
m_out.jump(continuation); |
| 562 |
m_out.appendTo(continuation, lastNext); |
605 |
m_out.appendTo(continuation, lastNext); |
| 563 |
} |
606 |
} |
|
Lines 585-591
private:
Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp_sec20
|
| 585 |
// We don't have a negate-with-overflow intrinsic. Hopefully this |
628 |
// We don't have a negate-with-overflow intrinsic. Hopefully this |
| 586 |
// does the trick, though. |
629 |
// does the trick, though. |
| 587 |
LValue overflowResult = m_out.subWithOverflow32(m_out.int32Zero, value); |
630 |
LValue overflowResult = m_out.subWithOverflow32(m_out.int32Zero, value); |
| 588 |
speculate(Overflow, 0, 0, m_out.extractValue(overflowResult, 1)); |
631 |
speculate(Overflow, noValue(), 0, m_out.extractValue(overflowResult, 1)); |
| 589 |
result = m_out.extractValue(overflowResult, 0); |
632 |
result = m_out.extractValue(overflowResult, 0); |
| 590 |
} |
633 |
} |
| 591 |
|
634 |
|
|
Lines 656-662
private:
Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp_sec21
|
| 656 |
|
699 |
|
| 657 |
LValue value = lowInt32(m_node->child1()); |
700 |
LValue value = lowInt32(m_node->child1()); |
| 658 |
speculateForward( |
701 |
speculateForward( |
| 659 |
Overflow, 0, 0, m_out.lessThan(value, m_out.int32Zero), |
702 |
Overflow, noValue(), 0, m_out.lessThan(value, m_out.int32Zero), |
| 660 |
FormattedValue(ValueFormatUInt32, value)); |
703 |
FormattedValue(ValueFormatUInt32, value)); |
| 661 |
m_int32Values.add(m_node, value); |
704 |
m_int32Values.add(m_node, value); |
| 662 |
} |
705 |
} |
|
Lines 675-681
private:
Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp_sec22
|
| 675 |
|
718 |
|
| 676 |
if (m_node->structureSet().size() == 1) { |
719 |
if (m_node->structureSet().size() == 1) { |
| 677 |
speculate( |
720 |
speculate( |
| 678 |
exitKind, cell, 0, |
721 |
exitKind, jsValueValue(cell), 0, |
| 679 |
m_out.notEqual(structure, weakPointer(m_node->structureSet()[0]))); |
722 |
m_out.notEqual(structure, weakPointer(m_node->structureSet()[0]))); |
| 680 |
return; |
723 |
return; |
| 681 |
} |
724 |
} |
|
Lines 692-698
private:
Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp_sec23
|
| 692 |
} |
735 |
} |
| 693 |
|
736 |
|
| 694 |
speculate( |
737 |
speculate( |
| 695 |
exitKind, cell, 0, |
738 |
exitKind, jsValueValue(cell), 0, |
| 696 |
m_out.notEqual(structure, weakPointer(m_node->structureSet().last()))); |
739 |
m_out.notEqual(structure, weakPointer(m_node->structureSet().last()))); |
| 697 |
|
740 |
|
| 698 |
m_out.appendTo(continuation, lastNext); |
741 |
m_out.appendTo(continuation, lastNext); |
|
Lines 755-761
private:
Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp_sec24
|
| 755 |
case Array::Contiguous: { |
798 |
case Array::Contiguous: { |
| 756 |
if (m_node->arrayMode().isInBounds()) { |
799 |
if (m_node->arrayMode().isInBounds()) { |
| 757 |
speculate( |
800 |
speculate( |
| 758 |
OutOfBounds, 0, 0, |
801 |
OutOfBounds, noValue(), 0, |
| 759 |
m_out.aboveOrEqual( |
802 |
m_out.aboveOrEqual( |
| 760 |
index, m_out.load32(storage, m_heaps.Butterfly_publicLength))); |
803 |
index, m_out.load32(storage, m_heaps.Butterfly_publicLength))); |
| 761 |
|
804 |
|
|
Lines 764-770
private:
Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp_sec25
|
| 764 |
m_heaps.indexedInt32Properties : m_heaps.indexedContiguousProperties, |
807 |
m_heaps.indexedInt32Properties : m_heaps.indexedContiguousProperties, |
| 765 |
storage, m_out.zeroExt(index, m_out.intPtr), |
808 |
storage, m_out.zeroExt(index, m_out.intPtr), |
| 766 |
m_state.forNode(m_node->child2()).m_value)); |
809 |
m_state.forNode(m_node->child2()).m_value)); |
| 767 |
speculate(LoadFromHole, 0, 0, m_out.isZero64(result)); |
810 |
speculate(LoadFromHole, noValue(), 0, m_out.isZero64(result)); |
| 768 |
m_jsValueValues.add(m_node, result); |
811 |
m_jsValueValues.add(m_node, result); |
| 769 |
break; |
812 |
break; |
| 770 |
} |
813 |
} |
|
Lines 865-924
private:
Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp_sec26
|
| 865 |
} |
908 |
} |
| 866 |
} |
909 |
} |
| 867 |
|
910 |
|
| 868 |
void speculateBackward(ExitKind, LValue, Node*, LValue failCondition) |
911 |
void speculateBackward( |
|
|
912 |
ExitKind kind, FormattedValue lowValue, Node* highValue, LValue failCondition) |
| 869 |
{ |
913 |
{ |
| 870 |
LBasicBlock failCase = m_out.newBlock(); |
914 |
appendOSRExit( |
| 871 |
LBasicBlock continuation = m_out.newBlock(); |
915 |
kind, lowValue, highValue, failCondition, BackwardSpeculation, FormattedValue()); |
| 872 |
|
|
|
| 873 |
m_out.branch(failCondition, failCase, continuation); |
| 874 |
LBasicBlock lastNext = m_out.appendTo(failCase, continuation); |
| 875 |
// FIXME: Implement OSR exit. |
| 876 |
// https://bugs.webkit.org/show_bug.cgi?id=113623 |
| 877 |
m_out.call(m_abortFunction); |
| 878 |
m_out.unreachable(); |
| 879 |
m_out.appendTo(continuation, lastNext); |
| 880 |
} |
916 |
} |
| 881 |
|
917 |
|
| 882 |
void speculateForward(ExitKind kind, LValue lowValue, Node* highValue, LValue failCondition, const FormattedValue&) |
918 |
void speculateForward( |
|
|
919 |
ExitKind kind, FormattedValue lowValue, Node* highValue, LValue failCondition, |
| 920 |
const FormattedValue& recovery) |
| 883 |
{ |
921 |
{ |
| 884 |
speculateBackward(kind, lowValue, highValue, failCondition); |
922 |
appendOSRExit( |
| 885 |
// FIXME: Implement rewiring of OSR exit to forward. |
923 |
kind, lowValue, highValue, failCondition, ForwardSpeculation, recovery); |
| 886 |
// https://bugs.webkit.org/show_bug.cgi?id=113623 |
|
|
| 887 |
} |
924 |
} |
| 888 |
|
925 |
|
| 889 |
void speculate(ExitKind kind, LValue lowValue, Node* highValue, LValue failCondition) |
926 |
void speculate( |
|
|
927 |
ExitKind kind, FormattedValue lowValue, Node* highValue, LValue failCondition) |
| 890 |
{ |
928 |
{ |
| 891 |
speculateBackward(kind, lowValue, highValue, failCondition); |
929 |
appendOSRExit( |
| 892 |
// FIXME: Implement rewiring the OSR exit to forward, if m_direction == ForwardDirection. |
930 |
kind, lowValue, highValue, failCondition, m_direction, FormattedValue()); |
| 893 |
// https://bugs.webkit.org/show_bug.cgi?id=113623 |
|
|
| 894 |
} |
931 |
} |
| 895 |
|
932 |
|
| 896 |
void terminate(ExitKind kind) |
933 |
void terminate(ExitKind kind) |
| 897 |
{ |
934 |
{ |
| 898 |
speculate(kind, 0, 0, m_out.booleanTrue); |
935 |
speculate(kind, noValue(), 0, m_out.booleanTrue); |
| 899 |
} |
936 |
} |
| 900 |
|
937 |
|
| 901 |
void backwardTypeCheck(LValue lowValue, Edge highValue, SpeculatedType typesPassedThrough, LValue failCondition) |
938 |
void backwardTypeCheck( |
|
|
939 |
FormattedValue lowValue, Edge highValue, SpeculatedType typesPassedThrough, |
| 940 |
LValue failCondition) |
| 902 |
{ |
941 |
{ |
| 903 |
if (!m_state.needsTypeCheck(highValue, typesPassedThrough)) |
942 |
appendTypeCheck( |
| 904 |
return; |
943 |
lowValue, highValue, typesPassedThrough, failCondition, BackwardSpeculation, |
| 905 |
ASSERT(mayHaveTypeCheck(highValue.useKind())); |
944 |
FormattedValue()); |
| 906 |
speculateBackward(BadType, lowValue, highValue.node(), failCondition); |
|
|
| 907 |
m_state.forNode(highValue).filter(typesPassedThrough); |
| 908 |
} |
945 |
} |
| 909 |
|
946 |
|
| 910 |
void forwardTypeCheck(LValue lowValue, Edge highValue, SpeculatedType typesPassedThrough, LValue failCondition) |
947 |
void forwardTypeCheck( |
|
|
948 |
FormattedValue lowValue, Edge highValue, SpeculatedType typesPassedThrough, |
| 949 |
LValue failCondition) |
| 911 |
{ |
950 |
{ |
| 912 |
backwardTypeCheck(lowValue, highValue, typesPassedThrough, failCondition); |
951 |
appendTypeCheck( |
| 913 |
// FIXME: Implement rewiring of OSR exit to forward. |
952 |
lowValue, highValue, typesPassedThrough, failCondition, ForwardSpeculation, |
| 914 |
// https://bugs.webkit.org/show_bug.cgi?id=113623 |
953 |
FormattedValue()); |
| 915 |
} |
954 |
} |
| 916 |
|
955 |
|
| 917 |
void typeCheck(LValue lowValue, Edge highValue, SpeculatedType typesPassedThrough, LValue failCondition) |
956 |
void typeCheck( |
|
|
957 |
FormattedValue lowValue, Edge highValue, SpeculatedType typesPassedThrough, |
| 958 |
LValue failCondition) |
| 918 |
{ |
959 |
{ |
| 919 |
backwardTypeCheck(lowValue, highValue, typesPassedThrough, failCondition); |
960 |
appendTypeCheck( |
| 920 |
// FIXME: Implement rewiring of OSR exit to forward, if m_direction == ForwardDirection. |
961 |
lowValue, highValue, typesPassedThrough, failCondition, m_direction, |
| 921 |
// https://bugs.webkit.org/show_bug.cgi?id=113623 |
962 |
FormattedValue()); |
|
|
963 |
} |
| 964 |
|
| 965 |
void appendTypeCheck( |
| 966 |
FormattedValue lowValue, Edge highValue, SpeculatedType typesPassedThrough, |
| 967 |
LValue failCondition, SpeculationDirection direction, FormattedValue recovery) |
| 968 |
{ |
| 969 |
if (!m_state.needsTypeCheck(highValue, typesPassedThrough)) |
| 970 |
return; |
| 971 |
ASSERT(mayHaveTypeCheck(highValue.useKind())); |
| 972 |
appendOSRExit(BadType, lowValue, highValue.node(), failCondition, direction, recovery); |
| 973 |
m_state.forNode(highValue).filter(typesPassedThrough); |
| 922 |
} |
974 |
} |
| 923 |
|
975 |
|
| 924 |
LValue lowInt32(Edge edge, OperandSpeculationMode mode = AutomaticOperandSpeculation) |
976 |
LValue lowInt32(Edge edge, OperandSpeculationMode mode = AutomaticOperandSpeculation) |
|
Lines 929-935
private:
Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp_sec27
|
| 929 |
return result; |
981 |
return result; |
| 930 |
|
982 |
|
| 931 |
if (LValue boxedResult = m_jsValueValues.get(edge.node())) { |
983 |
if (LValue boxedResult = m_jsValueValues.get(edge.node())) { |
| 932 |
FTL_TYPE_CHECK(boxedResult, edge, SpecInt32, isNotInt32(boxedResult)); |
984 |
FTL_TYPE_CHECK( |
|
|
985 |
jsValueValue(boxedResult), edge, SpecInt32, isNotInt32(boxedResult)); |
| 933 |
LValue result = unboxInt32(boxedResult); |
986 |
LValue result = unboxInt32(boxedResult); |
| 934 |
m_int32Values.add(edge.node(), result); |
987 |
m_int32Values.add(edge.node(), result); |
| 935 |
return result; |
988 |
return result; |
|
Lines 945-951
private:
Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp_sec28
|
| 945 |
ASSERT_UNUSED(mode, mode == ManualOperandSpeculation || isCell(edge.useKind())); |
998 |
ASSERT_UNUSED(mode, mode == ManualOperandSpeculation || isCell(edge.useKind())); |
| 946 |
|
999 |
|
| 947 |
if (LValue uncheckedResult = m_jsValueValues.get(edge.node())) { |
1000 |
if (LValue uncheckedResult = m_jsValueValues.get(edge.node())) { |
| 948 |
FTL_TYPE_CHECK(uncheckedResult, edge, SpecCell, isNotCell(uncheckedResult)); |
1001 |
FTL_TYPE_CHECK( |
|
|
1002 |
jsValueValue(uncheckedResult), edge, SpecCell, isNotCell(uncheckedResult)); |
| 949 |
return uncheckedResult; |
1003 |
return uncheckedResult; |
| 950 |
} |
1004 |
} |
| 951 |
|
1005 |
|
|
Lines 971-977
private:
Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp_sec29
|
| 971 |
return result; |
1025 |
return result; |
| 972 |
|
1026 |
|
| 973 |
if (LValue unboxedResult = m_jsValueValues.get(edge.node())) { |
1027 |
if (LValue unboxedResult = m_jsValueValues.get(edge.node())) { |
| 974 |
FTL_TYPE_CHECK(unboxedResult, edge, SpecBoolean, isNotBoolean(unboxedResult)); |
1028 |
FTL_TYPE_CHECK( |
|
|
1029 |
jsValueValue(unboxedResult), edge, SpecBoolean, isNotBoolean(unboxedResult)); |
| 975 |
LValue result = unboxBoolean(unboxedResult); |
1030 |
LValue result = unboxBoolean(unboxedResult); |
| 976 |
m_booleanValues.add(edge.node(), result); |
1031 |
m_booleanValues.add(edge.node(), result); |
| 977 |
return result; |
1032 |
return result; |
|
Lines 1094-1100
private:
Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp_sec30
|
| 1094 |
void speculateObject(Edge edge, LValue cell) |
1149 |
void speculateObject(Edge edge, LValue cell) |
| 1095 |
{ |
1150 |
{ |
| 1096 |
FTL_TYPE_CHECK( |
1151 |
FTL_TYPE_CHECK( |
| 1097 |
cell, edge, SpecObject, |
1152 |
jsValueValue(cell), edge, SpecObject, |
| 1098 |
m_out.equal( |
1153 |
m_out.equal( |
| 1099 |
m_out.loadPtr(cell, m_heaps.JSCell_structure), |
1154 |
m_out.loadPtr(cell, m_heaps.JSCell_structure), |
| 1100 |
m_out.constIntPtr(globalData().stringStructure.get()))); |
1155 |
m_out.constIntPtr(globalData().stringStructure.get()))); |
|
Lines 1105-1110
private:
Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp_sec31
|
| 1105 |
speculateObject(edge, lowCell(edge)); |
1160 |
speculateObject(edge, lowCell(edge)); |
| 1106 |
} |
1161 |
} |
| 1107 |
|
1162 |
|
|
|
1163 |
bool isLive(Node* node) |
| 1164 |
{ |
| 1165 |
HashMap<Node*, unsigned>::iterator iter = m_timeToLive.find(node); |
| 1166 |
ASSERT(iter != m_timeToLive.end()); |
| 1167 |
return !!iter->value; |
| 1168 |
} |
| 1169 |
|
| 1170 |
void use(Edge edge) |
| 1171 |
{ |
| 1172 |
HashMap<Node*, unsigned>::iterator iter = m_timeToLive.find(edge.node()); |
| 1173 |
ASSERT(iter != m_timeToLive.end()); |
| 1174 |
ASSERT(iter->value); |
| 1175 |
iter->value--; |
| 1176 |
} |
| 1177 |
|
| 1178 |
// Wrapper used only for DFG_NODE_DO_TO_CHILDREN |
| 1179 |
void use(Node*, Edge edge) |
| 1180 |
{ |
| 1181 |
use(edge); |
| 1182 |
} |
| 1183 |
|
| 1184 |
void initializeOSRExitStateForBlock() |
| 1185 |
{ |
| 1186 |
for (unsigned i = m_valueSources.size(); i--;) { |
| 1187 |
Node* node = m_highBlock->variablesAtHead[i]; |
| 1188 |
if (!node) { |
| 1189 |
m_valueSources[i] = ValueSource(SourceIsDead); |
| 1190 |
continue; |
| 1191 |
} |
| 1192 |
|
| 1193 |
VariableAccessData* variable = node->variableAccessData(); |
| 1194 |
SpeculatedType prediction = variable->argumentAwarePrediction(); |
| 1195 |
|
| 1196 |
if (variable->isArgumentsAlias()) { |
| 1197 |
m_valueSources[i] = ValueSource(ArgumentsSource); |
| 1198 |
continue; |
| 1199 |
} |
| 1200 |
|
| 1201 |
if (!node->shouldGenerate()) { |
| 1202 |
m_valueSources[i] = ValueSource(SourceIsDead); |
| 1203 |
continue; |
| 1204 |
} |
| 1205 |
|
| 1206 |
if (m_flushedLocalOps.contains(node)) { |
| 1207 |
// This value will have been flushed to the JSStack in some form or |
| 1208 |
// another. |
| 1209 |
|
| 1210 |
if (variable->shouldUnboxIfPossible()) { |
| 1211 |
if (variable->shouldUseDoubleFormat()) { |
| 1212 |
m_valueSources[i] = ValueSource(DoubleInJSStack); |
| 1213 |
continue; |
| 1214 |
} |
| 1215 |
|
| 1216 |
if (isInt32Speculation(prediction)) { |
| 1217 |
m_valueSources[i] = ValueSource(Int32InJSStack); |
| 1218 |
continue; |
| 1219 |
} |
| 1220 |
} |
| 1221 |
|
| 1222 |
m_valueSources[i] = ValueSource(ValueInJSStack); |
| 1223 |
continue; |
| 1224 |
} |
| 1225 |
|
| 1226 |
if (variable->shouldUnboxIfPossible()) { |
| 1227 |
if (variable->shouldUseDoubleFormat()) { |
| 1228 |
m_valueSources[i] = ValueSource(ValueInLocals); |
| 1229 |
continue; |
| 1230 |
} |
| 1231 |
|
| 1232 |
if (isInt32Speculation(prediction)) { |
| 1233 |
m_valueSources[i] = ValueSource(Int32InLocals); |
| 1234 |
continue; |
| 1235 |
} |
| 1236 |
|
| 1237 |
if (isBooleanSpeculation(prediction)) { |
| 1238 |
m_valueSources[i] = ValueSource(BooleanInLocals); |
| 1239 |
continue; |
| 1240 |
} |
| 1241 |
} |
| 1242 |
|
| 1243 |
m_valueSources[i] = ValueSource(ValueInLocals); |
| 1244 |
} |
| 1245 |
} |
| 1246 |
|
| 1247 |
void appendOSRExit( |
| 1248 |
ExitKind kind, FormattedValue lowValue, Node* highValue, LValue failCondition, |
| 1249 |
SpeculationDirection direction, FormattedValue recovery) |
| 1250 |
{ |
| 1251 |
m_ftlState.jitCode->osrExit.append( |
| 1252 |
OSRExit( |
| 1253 |
kind, lowValue.format(), m_graph.methodOfGettingAValueProfileFor(highValue), |
| 1254 |
m_node->codeOrigin, m_lastSetOperand, m_valueSources.numberOfArguments(), |
| 1255 |
m_valueSources.numberOfLocals())); |
| 1256 |
m_ftlState.osrExit.append(OSRExitCompilationInfo()); |
| 1257 |
|
| 1258 |
OSRExit& exit = m_ftlState.jitCode->osrExit.last(); |
| 1259 |
OSRExitCompilationInfo& info = m_ftlState.osrExit.last(); |
| 1260 |
|
| 1261 |
LBasicBlock failCase = m_out.newBlock(); |
| 1262 |
LBasicBlock continuation = m_out.newBlock(); |
| 1263 |
|
| 1264 |
m_out.branch(failCondition, failCase, continuation); |
| 1265 |
|
| 1266 |
m_out.appendTo(m_prologue); |
| 1267 |
info.m_thunkAddress = buildAlloca(m_out.m_builder, m_out.intPtr); |
| 1268 |
|
| 1269 |
LBasicBlock lastNext = m_out.appendTo(failCase, continuation); |
| 1270 |
|
| 1271 |
ExitArgumentList arguments; |
| 1272 |
arguments.append(m_callFrame); |
| 1273 |
if (!!lowValue) |
| 1274 |
arguments.append(lowValue.value()); |
| 1275 |
|
| 1276 |
for (unsigned i = 0; i < exit.m_values.size(); ++i) { |
| 1277 |
ValueSource source = m_valueSources[i]; |
| 1278 |
|
| 1279 |
switch (source.kind()) { |
| 1280 |
case ValueInJSStack: |
| 1281 |
exit.m_values[i] = ExitValue::inJSStack(); |
| 1282 |
break; |
| 1283 |
case Int32InJSStack: |
| 1284 |
exit.m_values[i] = ExitValue::inJSStackAsInt32(); |
| 1285 |
break; |
| 1286 |
case DoubleInJSStack: |
| 1287 |
exit.m_values[i] = ExitValue::inJSStackAsDouble(); |
| 1288 |
break; |
| 1289 |
case ValueInLocals: |
| 1290 |
addExitArgument( |
| 1291 |
exit, arguments, i, ValueFormatJSValue, m_out.get(m_locals64[i])); |
| 1292 |
break; |
| 1293 |
case Int32InLocals: |
| 1294 |
addExitArgument( |
| 1295 |
exit, arguments, i, ValueFormatInt32, m_out.get(m_locals32[i])); |
| 1296 |
break; |
| 1297 |
case BooleanInLocals: |
| 1298 |
addExitArgument( |
| 1299 |
exit, arguments, i, ValueFormatBoolean, m_out.get(m_localsBoolean[i])); |
| 1300 |
break; |
| 1301 |
case DoubleInLocals: |
| 1302 |
// FIXME: implement doubles in FTL. |
| 1303 |
// https://bugs.webkit.org/show_bug.cgi?id=113624 |
| 1304 |
RELEASE_ASSERT_NOT_REACHED(); |
| 1305 |
break; |
| 1306 |
case ArgumentsSource: |
| 1307 |
// FIXME: implement PhantomArguments. |
| 1308 |
// https://bugs.webkit.org/show_bug.cgi?id=113986 |
| 1309 |
RELEASE_ASSERT_NOT_REACHED(); |
| 1310 |
break; |
| 1311 |
case SourceIsDead: |
| 1312 |
exit.m_values[i] = ExitValue::dead(); |
| 1313 |
break; |
| 1314 |
case HaveNode: |
| 1315 |
addExitArgumentForNode(exit, arguments, i, source.node()); |
| 1316 |
break; |
| 1317 |
default: |
| 1318 |
RELEASE_ASSERT_NOT_REACHED(); |
| 1319 |
break; |
| 1320 |
} |
| 1321 |
} |
| 1322 |
|
| 1323 |
if (direction == ForwardSpeculation) |
| 1324 |
exit.convertToForward(m_highBlock, m_node, m_nodeIndex, recovery, arguments); |
| 1325 |
|
| 1326 |
// So, the really lame thing here is that we have to build an LLVM function type. |
| 1327 |
// Booo. |
| 1328 |
Vector<LType, 16> argumentTypes; |
| 1329 |
for (unsigned i = 0; i < arguments.size(); ++i) |
| 1330 |
argumentTypes.append(typeOf(arguments[i])); |
| 1331 |
|
| 1332 |
m_out.call( |
| 1333 |
m_out.intToPtr( |
| 1334 |
m_out.get(info.m_thunkAddress), |
| 1335 |
pointerType(functionType(m_out.voidType, argumentTypes))), |
| 1336 |
arguments); |
| 1337 |
m_out.unreachable(); |
| 1338 |
|
| 1339 |
m_out.appendTo(continuation, lastNext); |
| 1340 |
} |
| 1341 |
|
| 1342 |
void addExitArgumentForNode( |
| 1343 |
OSRExit& exit, ExitArgumentList& arguments, unsigned index, Node* node) |
| 1344 |
{ |
| 1345 |
ASSERT(node->shouldGenerate()); |
| 1346 |
ASSERT(node->hasResult()); |
| 1347 |
|
| 1348 |
if (tryToSetConstantExitArgument(exit, index, node)) |
| 1349 |
return; |
| 1350 |
|
| 1351 |
if (!isLive(node)) { |
| 1352 |
bool found = false; |
| 1353 |
|
| 1354 |
if (needsOSRBackwardRewiring(node->op())) { |
| 1355 |
node = node->child1().node(); |
| 1356 |
if (tryToSetConstantExitArgument(exit, index, node)) |
| 1357 |
return; |
| 1358 |
if (isLive(node)) |
| 1359 |
found = true; |
| 1360 |
} |
| 1361 |
|
| 1362 |
if (!found) { |
| 1363 |
Node* int32ToDouble = 0; |
| 1364 |
Node* valueToInt32 = 0; |
| 1365 |
Node* uint32ToNumber = 0; |
| 1366 |
Node* doubleAsInt32 = 0; |
| 1367 |
|
| 1368 |
HashMap<Node*, unsigned>::iterator iter = m_timeToLive.begin(); |
| 1369 |
HashMap<Node*, unsigned>::iterator end = m_timeToLive.end(); |
| 1370 |
for (; iter != end; ++iter) { |
| 1371 |
if (!iter->value) |
| 1372 |
continue; |
| 1373 |
Node* candidate = iter->key; |
| 1374 |
if (!candidate->child1()) |
| 1375 |
continue; |
| 1376 |
if (candidate->child1() != node) |
| 1377 |
continue; |
| 1378 |
switch (candidate->op()) { |
| 1379 |
case Int32ToDouble: |
| 1380 |
case ForwardInt32ToDouble: |
| 1381 |
int32ToDouble = candidate; |
| 1382 |
break; |
| 1383 |
case ValueToInt32: |
| 1384 |
valueToInt32 = candidate; |
| 1385 |
break; |
| 1386 |
case UInt32ToNumber: |
| 1387 |
uint32ToNumber = candidate; |
| 1388 |
break; |
| 1389 |
case DoubleAsInt32: |
| 1390 |
uint32ToNumber = candidate; |
| 1391 |
break; |
| 1392 |
default: |
| 1393 |
ASSERT(!needsOSRForwardRewiring(candidate->op())); |
| 1394 |
break; |
| 1395 |
} |
| 1396 |
} |
| 1397 |
|
| 1398 |
if (doubleAsInt32) |
| 1399 |
node = doubleAsInt32; |
| 1400 |
else if (int32ToDouble) |
| 1401 |
node = int32ToDouble; |
| 1402 |
else if (valueToInt32) |
| 1403 |
node = valueToInt32; |
| 1404 |
else if (uint32ToNumber) |
| 1405 |
node = uint32ToNumber; |
| 1406 |
|
| 1407 |
if (isLive(node)) |
| 1408 |
found = true; |
| 1409 |
} |
| 1410 |
|
| 1411 |
if (!found) { |
| 1412 |
exit.m_values[index] = ExitValue::dead(); |
| 1413 |
return; |
| 1414 |
} |
| 1415 |
} |
| 1416 |
|
| 1417 |
ASSERT(isLive(node)); |
| 1418 |
|
| 1419 |
if (LValue result = m_int32Values.get(node)) { |
| 1420 |
addExitArgument(exit, arguments, index, ValueFormatInt32, result); |
| 1421 |
return; |
| 1422 |
} |
| 1423 |
|
| 1424 |
if (LValue result = m_booleanValues.get(node)) { |
| 1425 |
addExitArgument(exit, arguments, index, ValueFormatBoolean, result); |
| 1426 |
return; |
| 1427 |
} |
| 1428 |
|
| 1429 |
if (LValue result = m_jsValueValues.get(node)) { |
| 1430 |
addExitArgument(exit, arguments, index, ValueFormatJSValue, result); |
| 1431 |
return; |
| 1432 |
} |
| 1433 |
|
| 1434 |
// FIXME: Implement doubles in the FTL. |
| 1435 |
// https://bugs.webkit.org/show_bug.cgi?id=113624 |
| 1436 |
RELEASE_ASSERT_NOT_REACHED(); |
| 1437 |
} |
| 1438 |
|
| 1439 |
bool tryToSetConstantExitArgument(OSRExit& exit, unsigned index, Node* node) |
| 1440 |
{ |
| 1441 |
if (!node) |
| 1442 |
return false; |
| 1443 |
|
| 1444 |
switch (node->op()) { |
| 1445 |
case JSConstant: |
| 1446 |
case WeakJSConstant: |
| 1447 |
exit.m_values[index] = ExitValue::constant(m_graph.valueOfJSConstant(node)); |
| 1448 |
return true; |
| 1449 |
case PhantomArguments: |
| 1450 |
// FIXME: implement PhantomArguments. |
| 1451 |
// https://bugs.webkit.org/show_bug.cgi?id=113986 |
| 1452 |
RELEASE_ASSERT_NOT_REACHED(); |
| 1453 |
return true; |
| 1454 |
default: |
| 1455 |
return false; |
| 1456 |
} |
| 1457 |
} |
| 1458 |
|
| 1459 |
void addExitArgument( |
| 1460 |
OSRExit& exit, ExitArgumentList& arguments, unsigned index, ValueFormat format, |
| 1461 |
LValue value) |
| 1462 |
{ |
| 1463 |
exit.m_values[index] = ExitValue::exitArgument(ExitArgument(format, arguments.size())); |
| 1464 |
arguments.append(value); |
| 1465 |
} |
| 1466 |
|
| 1467 |
void linkOSRExitsAndCompleteInitializationBlock() |
| 1468 |
{ |
| 1469 |
MacroAssemblerCodeRef osrExitThunk = |
| 1470 |
globalData().getCTIStub(osrExitGenerationThunkGenerator); |
| 1471 |
CodeLocationLabel target = CodeLocationLabel(osrExitThunk.code()); |
| 1472 |
|
| 1473 |
m_out.appendTo(m_initialization); |
| 1474 |
|
| 1475 |
LinkBuffer linkBuffer( |
| 1476 |
globalData(), &m_exitThunkGenerator, m_ftlState.graph.m_codeBlock, |
| 1477 |
JITCompilationMustSucceed); |
| 1478 |
|
| 1479 |
ASSERT(m_ftlState.osrExit.size() == m_ftlState.jitCode->osrExit.size()); |
| 1480 |
|
| 1481 |
for (unsigned i = 0; i < m_ftlState.osrExit.size(); ++i) { |
| 1482 |
OSRExitCompilationInfo& info = m_ftlState.osrExit[i]; |
| 1483 |
OSRExit& exit = m_ftlState.jitCode->osrExit[i]; |
| 1484 |
|
| 1485 |
linkBuffer.link(info.m_thunkJump, target); |
| 1486 |
|
| 1487 |
m_out.set( |
| 1488 |
m_out.constIntPtr( |
| 1489 |
linkBuffer.locationOf(info.m_thunkLabel).executableAddress()), |
| 1490 |
info.m_thunkAddress); |
| 1491 |
|
| 1492 |
exit.m_patchableCodeOffset = linkBuffer.offsetOf(info.m_thunkJump); |
| 1493 |
} |
| 1494 |
|
| 1495 |
m_ftlState.jitCode->initializeExitThunks( |
| 1496 |
FINALIZE_DFG_CODE( |
| 1497 |
linkBuffer, |
| 1498 |
("FTL exit thunks for %s", toCString(CodeBlockWithJITType(m_ftlState.graph.m_codeBlock,JITCode::FTLJIT)).data()))); |
| 1499 |
|
| 1500 |
m_out.jump(m_blocks.get(m_graph.m_blocks[0].get())); |
| 1501 |
} |
| 1502 |
|
| 1503 |
void observeMovHint(Node* node) |
| 1504 |
{ |
| 1505 |
ASSERT(node->containsMovHint()); |
| 1506 |
ASSERT(node->op() != ZombieHint); |
| 1507 |
|
| 1508 |
int operand = node->local(); |
| 1509 |
|
| 1510 |
m_lastSetOperand = operand; |
| 1511 |
m_valueSources[operand] = ValueSource(node->child1().node()); |
| 1512 |
} |
| 1513 |
|
| 1108 |
void addWeakReference(JSCell* target) |
1514 |
void addWeakReference(JSCell* target) |
| 1109 |
{ |
1515 |
{ |
| 1110 |
m_ftlState.jitCode->common.weakReferences.append( |
1516 |
m_ftlState.jitCode->common.weakReferences.append( |
|
Lines 1151-1162
private:
Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp_sec32
|
| 1151 |
Output m_out; |
1557 |
Output m_out; |
| 1152 |
|
1558 |
|
| 1153 |
LBasicBlock m_prologue; |
1559 |
LBasicBlock m_prologue; |
|
|
1560 |
LBasicBlock m_initialization; |
| 1154 |
HashMap<BasicBlock*, LBasicBlock> m_blocks; |
1561 |
HashMap<BasicBlock*, LBasicBlock> m_blocks; |
| 1155 |
|
1562 |
|
| 1156 |
LValue m_callFrame; |
1563 |
LValue m_callFrame; |
| 1157 |
LValue m_tagTypeNumber; |
1564 |
LValue m_tagTypeNumber; |
| 1158 |
LValue m_tagMask; |
1565 |
LValue m_tagMask; |
| 1159 |
LValue m_abortFunction; |
|
|
| 1160 |
|
1566 |
|
| 1161 |
HashSet<Node*> m_flushedLocalOps; |
1567 |
HashSet<Node*> m_flushedLocalOps; |
| 1162 |
Vector<Node*> m_flushedLocalOpWorklist; |
1568 |
Vector<Node*> m_flushedLocalOpWorklist; |
|
Lines 1165-1179
private:
Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp_sec33
|
| 1165 |
HashMap<Node*, LValue> m_jsValueValues; |
1571 |
HashMap<Node*, LValue> m_jsValueValues; |
| 1166 |
HashMap<Node*, LValue> m_booleanValues; |
1572 |
HashMap<Node*, LValue> m_booleanValues; |
| 1167 |
HashMap<Node*, LValue> m_storageValues; |
1573 |
HashMap<Node*, LValue> m_storageValues; |
|
|
1574 |
HashMap<Node*, unsigned> m_timeToLive; |
| 1168 |
|
1575 |
|
| 1169 |
Operands<LValue> m_localsBoolean; |
1576 |
Operands<LValue> m_localsBoolean; |
| 1170 |
Operands<LValue> m_locals32; |
1577 |
Operands<LValue> m_locals32; |
| 1171 |
Operands<LValue> m_locals64; |
1578 |
Operands<LValue> m_locals64; |
| 1172 |
|
1579 |
|
|
|
1580 |
Operands<ValueSource> m_valueSources; |
| 1581 |
int m_lastSetOperand; |
| 1582 |
ExitThunkGenerator m_exitThunkGenerator; |
| 1583 |
|
| 1173 |
AbstractState m_state; |
1584 |
AbstractState m_state; |
| 1174 |
BasicBlock* m_highBlock; |
1585 |
BasicBlock* m_highBlock; |
| 1175 |
BasicBlock* m_nextHighBlock; |
1586 |
BasicBlock* m_nextHighBlock; |
| 1176 |
LBasicBlock m_nextLowBlock; |
1587 |
LBasicBlock m_nextLowBlock; |
|
|
1588 |
unsigned m_nodeIndex; |
| 1177 |
Node* m_node; |
1589 |
Node* m_node; |
| 1178 |
SpeculationDirection m_direction; |
1590 |
SpeculationDirection m_direction; |
| 1179 |
}; |
1591 |
}; |