+ setIdentifiers(unlinkedCodeBlock->identifiers());
+ setConstantRegisters(unlinkedCodeBlock->constantRegisters());
+ if (unlinkedCodeBlock->usesGlobalObject())
+ m_constantRegisters[unlinkedCodeBlock->globalObjectRegister()].set(*m_vm, ownerExecutable, globalObject);
+ m_functionDecls.grow(unlinkedCodeBlock->numberOfFunctionDecls());
+ for (size_t count = unlinkedCodeBlock->numberOfFunctionDecls(), i = 0; i < count; ++i) {
+ UnlinkedFunctionExecutable* unlinkedExecutable = unlinkedCodeBlock->functionDecl(i);
+ unsigned lineCount = unlinkedExecutable->lineCount();
+ unsigned firstLine = ownerExecutable->lineNo() + unlinkedExecutable->firstLineOffset();
+ unsigned startColumn = unlinkedExecutable->functionStartColumn();
+ startColumn += (unlinkedExecutable->firstLineOffset() ? 1 : ownerExecutable->startColumn());
+ unsigned startOffset = sourceOffset + unlinkedExecutable->startOffset();
+ unsigned sourceLength = unlinkedExecutable->sourceLength();
+ SourceCode code(m_source, startOffset, startOffset + sourceLength, firstLine, startColumn);
+ FunctionExecutable* executable = FunctionExecutable::create(*m_vm, code, unlinkedExecutable, firstLine, firstLine + lineCount, startColumn);
+ m_functionDecls[i].set(*m_vm, ownerExecutable, executable);
+ }
+
+ m_functionExprs.grow(unlinkedCodeBlock->numberOfFunctionExprs());
+ for (size_t count = unlinkedCodeBlock->numberOfFunctionExprs(), i = 0; i < count; ++i) {
+ UnlinkedFunctionExecutable* unlinkedExecutable = unlinkedCodeBlock->functionExpr(i);
+ unsigned lineCount = unlinkedExecutable->lineCount();
+ unsigned firstLine = ownerExecutable->lineNo() + unlinkedExecutable->firstLineOffset();
+ unsigned startColumn = unlinkedExecutable->functionStartColumn();
+ startColumn += (unlinkedExecutable->firstLineOffset() ? 1 : ownerExecutable->startColumn());
+ unsigned startOffset = sourceOffset + unlinkedExecutable->startOffset();
+ unsigned sourceLength = unlinkedExecutable->sourceLength();
+ SourceCode code(m_source, startOffset, startOffset + sourceLength, firstLine, startColumn);
+ FunctionExecutable* executable = FunctionExecutable::create(*m_vm, code, unlinkedExecutable, firstLine, firstLine + lineCount, startColumn);
+ m_functionExprs[i].set(*m_vm, ownerExecutable, executable);
+ }
+
+ if (unlinkedCodeBlock->hasRareData()) {
+ createRareDataIfNecessary();
+ if (size_t count = unlinkedCodeBlock->constantBufferCount()) {
+ m_rareData->m_constantBuffers.grow(count);
+ for (size_t i = 0; i < count; i++) {
+ const UnlinkedCodeBlock::ConstantBuffer& buffer = unlinkedCodeBlock->constantBuffer(i);
+ m_rareData->m_constantBuffers[i] = buffer;
+ }
+ }
+ if (size_t count = unlinkedCodeBlock->numberOfExceptionHandlers()) {
+ m_rareData->m_exceptionHandlers.grow(count);
+ for (size_t i = 0; i < count; i++) {
+ const UnlinkedHandlerInfo& handler = unlinkedCodeBlock->exceptionHandler(i);
+ m_rareData->m_exceptionHandlers[i].start = handler.start;
+ m_rareData->m_exceptionHandlers[i].end = handler.end;
+ m_rareData->m_exceptionHandlers[i].target = handler.target;
+ m_rareData->m_exceptionHandlers[i].scopeDepth = handler.scopeDepth + baseScopeDepth;
+#if ENABLE(JIT) && ENABLE(LLINT)
+ m_rareData->m_exceptionHandlers[i].nativeCode = CodeLocationLabel(MacroAssemblerCodePtr::createFromExecutableAddress(LLInt::getCodePtr(llint_op_catch)));
+#endif
+ }
+ }
+
+ if (size_t count = unlinkedCodeBlock->numberOfStringSwitchJumpTables()) {
+ m_rareData->m_stringSwitchJumpTables.grow(count);
+ for (size_t i = 0; i < count; i++) {
+ UnlinkedStringJumpTable::StringOffsetTable::iterator ptr = unlinkedCodeBlock->stringSwitchJumpTable(i).offsetTable.begin();
+ UnlinkedStringJumpTable::StringOffsetTable::iterator end = unlinkedCodeBlock->stringSwitchJumpTable(i).offsetTable.end();
+ for (; ptr != end; ++ptr) {
+ OffsetLocation offset;
+ offset.branchOffset = ptr->value;
+ m_rareData->m_stringSwitchJumpTables[i].offsetTable.add(ptr->key, offset);
+ }
+ }
+ }
+
+ if (size_t count = unlinkedCodeBlock->numberOfImmediateSwitchJumpTables()) {
+ m_rareData->m_immediateSwitchJumpTables.grow(count);
+ for (size_t i = 0; i < count; i++) {
+ UnlinkedSimpleJumpTable& sourceTable = unlinkedCodeBlock->immediateSwitchJumpTable(i);
+ SimpleJumpTable& destTable = m_rareData->m_immediateSwitchJumpTables[i];
+ destTable.branchOffsets = sourceTable.branchOffsets;
+ destTable.min = sourceTable.min;
+ }
+ }
+
+ if (size_t count = unlinkedCodeBlock->numberOfCharacterSwitchJumpTables()) {
+ m_rareData->m_characterSwitchJumpTables.grow(count);
+ for (size_t i = 0; i < count; i++) {
+ UnlinkedSimpleJumpTable& sourceTable = unlinkedCodeBlock->characterSwitchJumpTable(i);
+ SimpleJumpTable& destTable = m_rareData->m_characterSwitchJumpTables[i];
+ destTable.branchOffsets = sourceTable.branchOffsets;
+ destTable.min = sourceTable.min;
+ }
+ }
+ }
+
+ // Allocate metadata buffers for the bytecode
+#if ENABLE(LLINT)
+ if (size_t size = unlinkedCodeBlock->numberOfLLintCallLinkInfos())
+ m_llintCallLinkInfos.grow(size);
+#endif
+#if ENABLE(DFG_JIT)
+ if (size_t size = unlinkedCodeBlock->numberOfArrayProfiles())
+ m_arrayProfiles.grow(size);
+ if (size_t size = unlinkedCodeBlock->numberOfArrayAllocationProfiles())
+ m_arrayAllocationProfiles.grow(size);
+ if (size_t size = unlinkedCodeBlock->numberOfValueProfiles())
+ m_valueProfiles.grow(size);
+#endif
+ if (size_t size = unlinkedCodeBlock->numberOfObjectAllocationProfiles())
+ m_objectAllocationProfiles.grow(size);
+ if (size_t size = unlinkedCodeBlock->numberOfResolveOperations())
+ m_resolveOperations.grow(size);
+ if (size_t putToBaseCount = unlinkedCodeBlock->numberOfPutToBaseOperations()) {
+ m_putToBaseOperations.reserveInitialCapacity(putToBaseCount);
+ for (size_t i = 0; i < putToBaseCount; ++i)
+ m_putToBaseOperations.uncheckedAppend(PutToBaseOperation(isStrictMode()));
+ }
+
+ // Copy and translate the UnlinkedInstructions
+ size_t instructionCount = unlinkedCodeBlock->instructions().size();
+ UnlinkedInstruction* pc = unlinkedCodeBlock->instructions().data();
+ Vector<Instruction, 0, UnsafeVectorOverflow> instructions(instructionCount);
+ for (size_t i = 0; i < unlinkedCodeBlock->instructions().size(); ) {
+ unsigned opLength = opcodeLength(pc[i].u.opcode);
+ instructions[i] = vm()->interpreter->getOpcode(pc[i].u.opcode);
+ for (size_t j = 1; j < opLength; ++j) {
+ if (sizeof(int32_t) != sizeof(intptr_t))
+ instructions[i + j].u.pointer = 0;
+ instructions[i + j].u.operand = pc[i + j].u.operand;
+ }
+ switch (pc[i].u.opcode) {
+#if ENABLE(DFG_JIT)
+ case op_get_by_val:
+ case op_get_argument_by_val: {
+ int arrayProfileIndex = pc[i + opLength - 2].u.operand;
+ m_arrayProfiles[arrayProfileIndex] = ArrayProfile(i);
+
+ instructions[i + opLength - 2] = &m_arrayProfiles[arrayProfileIndex];
+ // fallthrough
+ }
+ case op_convert_this:
+ case op_get_by_id:
+ case op_call_put_result:
+ case op_get_callee: {
+ ValueProfile* profile = &m_valueProfiles[pc[i + opLength - 1].u.operand];
+ ASSERT(profile->m_bytecodeOffset == -1);
+ profile->m_bytecodeOffset = i;
+ instructions[i + opLength - 1] = profile;
+ break;
+ }
+ case op_put_by_val: {
+ int arrayProfileIndex = pc[i + opLength - 1].u.operand;
+ m_arrayProfiles[arrayProfileIndex] = ArrayProfile(i);
+ instructions[i + opLength - 1] = &m_arrayProfiles[arrayProfileIndex];
+ break;
+ }
+
+ case op_new_array:
+ case op_new_array_buffer:
+ case op_new_array_with_size: {
+ int arrayAllocationProfileIndex = pc[i + opLength - 1].u.operand;
+ instructions[i + opLength - 1] = &m_arrayAllocationProfiles[arrayAllocationProfileIndex];
+ break;
+ }
+#endif
+ case op_resolve_base:
+ case op_resolve_base_to_global:
+ case op_resolve_base_to_global_dynamic:
+ case op_resolve_base_to_scope:
+ case op_resolve_base_to_scope_with_top_scope_check: {
+ instructions[i + 4].u.resolveOperations = &m_resolveOperations[pc[i + 4].u.operand];
+ instructions[i + 5].u.putToBaseOperation = &m_putToBaseOperations[pc[i + 5].u.operand];
+#if ENABLE(DFG_JIT)
+ ValueProfile* profile = &m_valueProfiles[pc[i + opLength - 1].u.operand];
+ ASSERT(profile->m_bytecodeOffset == -1);
+ profile->m_bytecodeOffset = i;
+ ASSERT((opLength - 1) > 5);
+ instructions[i + opLength - 1] = profile;
+#endif
+ break;
+ }
+ case op_resolve_global_property:
+ case op_resolve_global_var:
+ case op_resolve_scoped_var:
+ case op_resolve_scoped_var_on_top_scope:
+ case op_resolve_scoped_var_with_top_scope_check: {
+ instructions[i + 3].u.resolveOperations = &m_resolveOperations[pc[i + 3].u.operand];
+ break;
+ }
+ case op_put_to_base:
+ case op_put_to_base_variable: {
+ instructions[i + 4].u.putToBaseOperation = &m_putToBaseOperations[pc[i + 4].u.operand];
+ break;
+ }
+ case op_resolve: {
+#if ENABLE(DFG_JIT)
+ ValueProfile* profile = &m_valueProfiles[pc[i + opLength - 1].u.operand];
+ ASSERT(profile->m_bytecodeOffset == -1);
+ profile->m_bytecodeOffset = i;
+ ASSERT((opLength - 1) > 3);
+ instructions[i + opLength - 1] = profile;
+#endif
+ instructions[i + 3].u.resolveOperations = &m_resolveOperations[pc[i + 3].u.operand];
+ break;
+ }
+ case op_resolve_with_base:
+ case op_resolve_with_this: {
+ instructions[i + 4].u.resolveOperations = &m_resolveOperations[pc[i + 4].u.operand];
+ if (pc[i].u.opcode != op_resolve_with_this)
+ instructions[i + 5].u.putToBaseOperation = &m_putToBaseOperations[pc[i + 5].u.operand];
+#if ENABLE(DFG_JIT)
+ ValueProfile* profile = &m_valueProfiles[pc[i + opLength - 1].u.operand];
+ ASSERT(profile->m_bytecodeOffset == -1);
+ profile->m_bytecodeOffset = i;
+ instructions[i + opLength - 1] = profile;
+#endif
+ break;
+ }
+ case op_new_object: {
+ int objectAllocationProfileIndex = pc[i + opLength - 1].u.operand;
+ ObjectAllocationProfile* objectAllocationProfile = &m_objectAllocationProfiles[objectAllocationProfileIndex];
+ int inferredInlineCapacity = pc[i + opLength - 2].u.operand;
+
+ instructions[i + opLength - 1] = objectAllocationProfile;
+ objectAllocationProfile->initialize(*vm(),
+ m_ownerExecutable.get(), m_globalObject->objectPrototype(), inferredInlineCapacity);
+ break;
+ }
+
+ case op_get_scoped_var: {
+#if ENABLE(DFG_JIT)
+ ValueProfile* profile = &m_valueProfiles[pc[i + opLength - 1].u.operand];
+ ASSERT(profile->m_bytecodeOffset == -1);
+ profile->m_bytecodeOffset = i;
+ instructions[i + opLength - 1] = profile;
+#endif
+ break;
+ }
+
+ case op_call:
+ case op_call_eval: {
+#if ENABLE(DFG_JIT)
+ int arrayProfileIndex = pc[i + opLength - 1].u.operand;
+ m_arrayProfiles[arrayProfileIndex] = ArrayProfile(i);
+ instructions[i + opLength - 1] = &m_arrayProfiles[arrayProfileIndex];
+#endif
+#if ENABLE(LLINT)
+ instructions[i + 4] = &m_llintCallLinkInfos[pc[i + 4].u.operand];
+#endif
+ break;
+ }
+ case op_construct:
+#if ENABLE(LLINT)
+ instructions[i + 4] = &m_llintCallLinkInfos[pc[i + 4].u.operand];
+#endif
+ break;
+ case op_get_by_id_out_of_line:
+ case op_get_by_id_self:
+ case op_get_by_id_proto:
+ case op_get_by_id_chain:
+ case op_get_by_id_getter_self:
+ case op_get_by_id_getter_proto:
+ case op_get_by_id_getter_chain:
+ case op_get_by_id_custom_self:
+ case op_get_by_id_custom_proto:
+ case op_get_by_id_custom_chain:
+ case op_get_by_id_generic:
+ case op_get_array_length:
+ case op_get_string_length:
+ CRASH();
+
+ case op_init_global_const_nop: {
+ ASSERT(codeType() == GlobalCode);
+ Identifier ident = identifier(pc[i + 4].u.operand);
+ SymbolTableEntry entry = globalObject->symbolTable()->get(ident.impl());
+ if (entry.isNull())
+ break;
+
+ if (entry.couldBeWatched()) {
+ instructions[i + 0] = vm()->interpreter->getOpcode(op_init_global_const_check);
+ instructions[i + 1] = &globalObject->registerAt(entry.getIndex());
+ instructions[i + 3] = entry.addressOfIsWatched();
+ break;
+ }
+
+ instructions[i + 0] = vm()->interpreter->getOpcode(op_init_global_const);
+ instructions[i + 1] = &globalObject->registerAt(entry.getIndex());
+ break;
+ }
+
+ case op_debug: {
+ instructions[i + 4] = columnNumberForBytecodeOffset(i);
+ break;
+ }
+
+ default:
+ break;
+ }
+ i += opLength;
+ }
+ m_instructions = WTF::RefCountedArray<Instruction>(instructions);
+
+ // Set optimization thresholds only after m_instructions is initialized, since these
+ // rely on the instruction count (and are in theory permitted to also inspect the
+ // instruction stream to more accurate assess the cost of tier-up).
+ optimizeAfterWarmUp();
+ jitAfterWarmUp();
+
+ if (Options::dumpGeneratedBytecodes())
+ dumpBytecode();
+ m_vm->finishedCompiling(this);