+LocalOSRAvailabilityCalculator::LocalOSRAvailabilityCalculator()
+{
+}
+
+LocalOSRAvailabilityCalculator::~LocalOSRAvailabilityCalculator()
+{
+}
+
+void LocalOSRAvailabilityCalculator::beginBlock(BasicBlock* block)
+{
+ m_availability = block->ssa->availabilityAtHead;
+}
+
+void LocalOSRAvailabilityCalculator::endBlock(BasicBlock* block)
+{
+ m_availability = block->ssa->availabilityAtTail;
+}
+
+void LocalOSRAvailabilityCalculator::executeNode(Node* node)
+{
+ switch (node->op()) {
+ case PutStack: {
+ StackAccessData* data = node->stackAccessData();
+ m_availability.m_locals.operand(data->local).setFlush(data->flushedAt());
+ break;
+ }
+
+ case KillStack: {
+ m_availability.m_locals.operand(node->unlinkedLocal()).setFlush(FlushedAt(ConflictingFlush));
+ break;
+ }
+
+ case GetStack: {
+ StackAccessData* data = node->stackAccessData();
+ m_availability.m_locals.operand(data->local) = Availability(node, data->flushedAt());
+ break;
+ }
+
+ case MovHint: {
+ m_availability.m_locals.operand(node->unlinkedLocal()).setNode(node->child1().node());
+ break;
+ }
+
+ case ZombieHint: {
+ m_availability.m_locals.operand(node->unlinkedLocal()).setNodeUnavailable();
+ break;
+ }
+
+ case LoadVarargs:
+ case ForwardVarargs: {
+ LoadVarargsData* data = node->loadVarargsData();
+ m_availability.m_locals.operand(data->count) =
+ Availability(FlushedAt(FlushedInt32, data->machineCount));
+ for (unsigned i = data->limit; i--;) {
+ m_availability.m_locals.operand(VirtualRegister(data->start.offset() + i)) =
+ Availability(FlushedAt(FlushedJSValue, VirtualRegister(data->machineStart.offset() + i)));
+ }
+ break;
+ }
+
+ case PhantomDirectArguments:
+ case PhantomClonedArguments: {
+ InlineCallFrame* inlineCallFrame = node->origin.semantic.inlineCallFrame;
+ if (!inlineCallFrame) {
+ // We don't need to record anything about how the arguments are to be recovered. It's just a
+ // given that we can read them from the stack.
+ break;
+ }
+
+ if (inlineCallFrame->isVarargs()) {
+ // Record how to read each argument and the argument count.
+ Availability argumentCount =
+ m_availability.m_locals.operand(inlineCallFrame->stackOffset + JSStack::ArgumentCount);
+
+ m_availability.m_heap.set(PromotedHeapLocation(ArgumentCountPLoc, node), argumentCount);
+ }
+
+ if (inlineCallFrame->isClosureCall) {
+ Availability callee = m_availability.m_locals.operand(
+ inlineCallFrame->stackOffset + JSStack::Callee);
+ m_availability.m_heap.set(PromotedHeapLocation(ArgumentsCalleePLoc, node), callee);
+ }
+
+ for (unsigned i = 0; i < inlineCallFrame->arguments.size() - 1; ++i) {
+ Availability argument = m_availability.m_locals.operand(
+ inlineCallFrame->stackOffset + CallFrame::argumentOffset(i));
+
+ m_availability.m_heap.set(PromotedHeapLocation(ArgumentPLoc, node, i), argument);
+ }
+ break;
+ }
+
+ case PutHint: {
+ m_availability.m_heap.set(
+ PromotedHeapLocation(node->child1().node(), node->promotedLocationDescriptor()),
+ Availability(node->child2().node()));
+ break;
+ }
+
+ default:
+ break;
+ }
+}
+