@@ -96,10 +96,13 @@ void DependencyGenContext::update(size_t dependencyStart, size_t id, size_t excl
9696 && maxDistance[dependencyStart / size] <= id);
9797
9898 for (auto it : param) {
99- VariableRef ref = variableList->variables .size ();
99+ if (variableList != nullptr ) {
100+ // Construct new variables.
101+ VariableRef ref = variableList->variables .size ();
100102
101- dependencies[dependencyStart + offset].insert (VARIABLE_SET (ref, Variable));
102- variableList->variables .push_back (VariableList::Variable (VARIABLE_SET (offset, Instruction::Offset), 0 , id));
103+ dependencies[dependencyStart + offset].insert (VARIABLE_SET (ref, Variable));
104+ variableList->variables .push_back (VariableList::Variable (VARIABLE_SET (offset, Instruction::Offset), 0 , id));
105+ }
103106
104107 offset += STACK_OFFSET (valueStackAllocatedSize (it));
105108 }
@@ -287,6 +290,7 @@ void JITCompiler::buildVariables(uint32_t requiredStackSize)
287290 size_t nextId = 0 ;
288291 size_t nextTryBlock = m_tryBlockStart;
289292
293+ // Create variables for each result or external values.
290294 for (InstructionListItem* item = m_first; item != nullptr ; item = item->next ()) {
291295 item->m_id = ++nextId;
292296
@@ -322,6 +326,7 @@ void JITCompiler::buildVariables(uint32_t requiredStackSize)
322326
323327 DependencyGenContext dependencyCtx (dependencySize, requiredStackSize);
324328 bool updateDeps = true ;
329+ std::vector<size_t > activeTryBlocks;
325330
326331 m_variableList = new VariableList (variableCount, requiredStackSize);
327332 nextTryBlock = m_tryBlockStart;
@@ -365,11 +370,16 @@ void JITCompiler::buildVariables(uint32_t requiredStackSize)
365370 }
366371 }
367372
373+ activeTryBlocks.push_back (nextTryBlock);
368374 nextTryBlock++;
369375 } while (nextTryBlock < tryBlocks ().size ()
370376 && tryBlocks ()[nextTryBlock].start == label);
371377 }
372378
379+ if (label->info () & Label::kHasCatchInfo ) {
380+ activeTryBlocks.pop_back ();
381+ }
382+
373383 for (size_t i = 0 ; i < requiredStackSize; ++i) {
374384 dependencyCtx.currentDependencies [i] = VARIABLE_SET_PTR (label);
375385 dependencyCtx.currentOptions [i] = 0 ;
@@ -424,7 +434,28 @@ void JITCompiler::buildVariables(uint32_t requiredStackSize)
424434 continue ;
425435 }
426436
427- if (instr->opcode () == ByteCode::ThrowOpcode || instr->opcode () == ByteCode::UnreachableOpcode) {
437+ if (activeTryBlocks.size () > 0 && (instr->group () == Instruction::Call || instr->opcode () == ByteCode::ThrowOpcode)) {
438+ // Every call or throw may jump to any active catch block. Future
439+ // optimizations could reduce these (e.g. a throw can be converted
440+ // to a jump if its target catch block is in the same function).
441+ for (auto blockIt : activeTryBlocks) {
442+ for (auto it : tryBlocks ()[blockIt].catchBlocks ) {
443+ if (it.tagIndex == std::numeric_limits<uint32_t >::max ()) {
444+ dependencyCtx.update (it.u .handler ->m_dependencyStart , instr->id ());
445+ } else {
446+ TagType* tagType = module ()->tagType (it.tagIndex );
447+ const ValueTypeVector& param = module ()->functionType (tagType->sigIndex ())->param ();
448+ Label* catchLabel = it.u .handler ;
449+
450+ dependencyCtx.update (catchLabel->m_dependencyStart , catchLabel->id (),
451+ STACK_OFFSET (it.stackSizeToBe ), param, nullptr );
452+ }
453+ }
454+ }
455+ }
456+
457+ if (instr->opcode () == ByteCode::ThrowOpcode || instr->opcode () == ByteCode::UnreachableOpcode
458+ || instr->opcode () == ByteCode::EndOpcode) {
428459 updateDeps = false ;
429460 continue ;
430461 }
@@ -495,6 +526,7 @@ void JITCompiler::buildVariables(uint32_t requiredStackSize)
495526 }
496527
497528 ASSERT (variableCount == m_variableList->variables .size ());
529+ ASSERT (activeTryBlocks.size () == 0 );
498530
499531 // Phase 2: the indirect instruction
500532 // references are computed for labels.
0 commit comments