Merge "Add allowRedundantMoreKeys attribute"
diff --git a/java-overridable/src/com/android/inputmethod/latin/settings/AdditionalFeaturesSettingUtils.java b/java-overridable/src/com/android/inputmethod/latin/settings/AdditionalFeaturesSettingUtils.java
index a18d582..1c02d7d 100644
--- a/java-overridable/src/com/android/inputmethod/latin/settings/AdditionalFeaturesSettingUtils.java
+++ b/java-overridable/src/com/android/inputmethod/latin/settings/AdditionalFeaturesSettingUtils.java
@@ -35,7 +35,7 @@
         // do nothing.
     }
 
-    public static void readAdditionalFeaturesPreferencesIntoArray(
+    public static void readAdditionalFeaturesPreferencesIntoArray(final Context context,
             final SharedPreferences prefs, final int[] additionalFeaturesPreferences) {
         // do nothing.
     }
diff --git a/java/src/com/android/inputmethod/keyboard/internal/PointerTrackerQueue.java b/java/src/com/android/inputmethod/keyboard/internal/PointerTrackerQueue.java
index 8e89e61e..556d74f 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/PointerTrackerQueue.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/PointerTrackerQueue.java
@@ -95,7 +95,7 @@
     public void releaseAllPointersOlderThan(final Element pointer, final long eventTime) {
         synchronized (mExpandableArrayOfActivePointers) {
             if (DEBUG) {
-                Log.d(TAG, "releaseAllPoniterOlderThan: " + pointer + " " + this);
+                Log.d(TAG, "releaseAllPointerOlderThan: " + pointer + " " + this);
             }
             final ArrayList<Element> expandableArray = mExpandableArrayOfActivePointers;
             final int arraySize = mArraySize;
@@ -144,9 +144,9 @@
         synchronized (mExpandableArrayOfActivePointers) {
             if (DEBUG) {
                 if (pointer == null) {
-                    Log.d(TAG, "releaseAllPoniters: " + this);
+                    Log.d(TAG, "releaseAllPointers: " + this);
                 } else {
-                    Log.d(TAG, "releaseAllPoniterExcept: " + pointer + " " + this);
+                    Log.d(TAG, "releaseAllPointerExcept: " + pointer + " " + this);
                 }
             }
             final ArrayList<Element> expandableArray = mExpandableArrayOfActivePointers;
diff --git a/java/src/com/android/inputmethod/latin/settings/SettingsValues.java b/java/src/com/android/inputmethod/latin/settings/SettingsValues.java
index 964d5ce..99f761c 100644
--- a/java/src/com/android/inputmethod/latin/settings/SettingsValues.java
+++ b/java/src/com/android/inputmethod/latin/settings/SettingsValues.java
@@ -180,7 +180,7 @@
         mAutoCorrectionEnabledPerUserSettings = mAutoCorrectEnabled
                 && !mInputAttributes.mInputTypeNoAutoCorrect;
         mSuggestionsEnabledPerUserSettings = readSuggestionsEnabled(prefs);
-        AdditionalFeaturesSettingUtils.readAdditionalFeaturesPreferencesIntoArray(
+        AdditionalFeaturesSettingUtils.readAdditionalFeaturesPreferencesIntoArray(context,
                 prefs, mAdditionalFeaturesSettingValues);
         mTextHighlightColorForAddToDictionaryIndicator = res.getColor(
                 R.color.text_decorator_add_to_dictionary_indicator_text_highlight_color);
diff --git a/native/jni/com_android_inputmethod_latin_BinaryDictionary.cpp b/native/jni/com_android_inputmethod_latin_BinaryDictionary.cpp
index 688ce44..e420f80 100644
--- a/native/jni/com_android_inputmethod_latin_BinaryDictionary.cpp
+++ b/native/jni/com_android_inputmethod_latin_BinaryDictionary.cpp
@@ -364,10 +364,12 @@
     int codePoints[codePointCount];
     env->GetIntArrayRegion(word, 0, codePointCount, codePoints);
     std::vector<UnigramProperty::ShortcutProperty> shortcuts;
-    std::vector<int> shortcutTargetCodePoints;
-    JniDataUtils::jintarrayToVector(env, shortcutTarget, &shortcutTargetCodePoints);
-    if (!shortcutTargetCodePoints.empty()) {
-        shortcuts.emplace_back(&shortcutTargetCodePoints, shortcutProbability);
+    {
+        std::vector<int> shortcutTargetCodePoints;
+        JniDataUtils::jintarrayToVector(env, shortcutTarget, &shortcutTargetCodePoints);
+        if (!shortcutTargetCodePoints.empty()) {
+            shortcuts.emplace_back(std::move(shortcutTargetCodePoints), shortcutProbability);
+        }
     }
     // Use 1 for count to indicate the word has inputted.
     const UnigramProperty unigramProperty(isBeginningOfSentence, isNotAWord,
@@ -401,11 +403,9 @@
     jsize wordLength = env->GetArrayLength(word);
     int wordCodePoints[wordLength];
     env->GetIntArrayRegion(word, 0, wordLength, wordCodePoints);
-    const std::vector<int> bigramTargetCodePoints(
-            wordCodePoints, wordCodePoints + wordLength);
     // Use 1 for count to indicate the bigram has inputted.
-    const BigramProperty bigramProperty(&bigramTargetCodePoints, probability,
-            timestamp, 0 /* level */, 1 /* count */);
+    const BigramProperty bigramProperty(CodePointArrayView(wordCodePoints, wordLength).toVector(),
+            probability, timestamp, 0 /* level */, 1 /* count */);
     return dictionary->addNgramEntry(&prevWordsInfo, &bigramProperty);
 }
 
@@ -483,12 +483,14 @@
         jintArray shortcutTarget = static_cast<jintArray>(
                 env->GetObjectField(languageModelParam, shortcutTargetFieldId));
         std::vector<UnigramProperty::ShortcutProperty> shortcuts;
-        std::vector<int> shortcutTargetCodePoints;
-        JniDataUtils::jintarrayToVector(env, shortcutTarget, &shortcutTargetCodePoints);
-        if (!shortcutTargetCodePoints.empty()) {
-            jint shortcutProbability =
-                    env->GetIntField(languageModelParam, shortcutProbabilityFieldId);
-            shortcuts.emplace_back(&shortcutTargetCodePoints, shortcutProbability);
+        {
+            std::vector<int> shortcutTargetCodePoints;
+            JniDataUtils::jintarrayToVector(env, shortcutTarget, &shortcutTargetCodePoints);
+            if (!shortcutTargetCodePoints.empty()) {
+                jint shortcutProbability =
+                        env->GetIntField(languageModelParam, shortcutProbabilityFieldId);
+                shortcuts.emplace_back(std::move(shortcutTargetCodePoints), shortcutProbability);
+            }
         }
         // Use 1 for count to indicate the word has inputted.
         const UnigramProperty unigramProperty(false /* isBeginningOfSentence */, isNotAWord,
@@ -498,11 +500,10 @@
                 &unigramProperty);
         if (word0) {
             jint bigramProbability = env->GetIntField(languageModelParam, bigramProbabilityFieldId);
-            const std::vector<int> bigramTargetCodePoints(
-                    word1CodePoints, word1CodePoints + word1Length);
             // Use 1 for count to indicate the bigram has inputted.
-            const BigramProperty bigramProperty(&bigramTargetCodePoints, bigramProbability,
-                    timestamp, 0 /* level */, 1 /* count */);
+            const BigramProperty bigramProperty(
+                    CodePointArrayView(word1CodePoints, word1Length).toVector(),
+                    bigramProbability, timestamp, 0 /* level */, 1 /* count */);
             const PrevWordsInfo prevWordsInfo(word0CodePoints, word0Length,
                     false /* isBeginningOfSentence */);
             dictionary->addNgramEntry(&prevWordsInfo, &bigramProperty);
diff --git a/native/jni/src/suggest/core/dictionary/property/bigram_property.h b/native/jni/src/suggest/core/dictionary/property/bigram_property.h
index 343af14..9e0baa0 100644
--- a/native/jni/src/suggest/core/dictionary/property/bigram_property.h
+++ b/native/jni/src/suggest/core/dictionary/property/bigram_property.h
@@ -26,9 +26,9 @@
 // TODO: Change to NgramProperty.
 class BigramProperty {
  public:
-    BigramProperty(const std::vector<int> *const targetCodePoints,
-            const int probability, const int timestamp, const int level, const int count)
-            : mTargetCodePoints(*targetCodePoints), mProbability(probability),
+    BigramProperty(const std::vector<int> &&targetCodePoints, const int probability,
+            const int timestamp, const int level, const int count)
+            : mTargetCodePoints(std::move(targetCodePoints)), mProbability(probability),
               mTimestamp(timestamp), mLevel(level), mCount(count) {}
 
     const std::vector<int> *getTargetCodePoints() const {
diff --git a/native/jni/src/suggest/core/dictionary/property/unigram_property.h b/native/jni/src/suggest/core/dictionary/property/unigram_property.h
index 65c8333..b7e7d66 100644
--- a/native/jni/src/suggest/core/dictionary/property/unigram_property.h
+++ b/native/jni/src/suggest/core/dictionary/property/unigram_property.h
@@ -27,8 +27,9 @@
  public:
     class ShortcutProperty {
      public:
-        ShortcutProperty(const std::vector<int> *const targetCodePoints, const int probability)
-                : mTargetCodePoints(*targetCodePoints), mProbability(probability) {}
+        ShortcutProperty(const std::vector<int> &&targetCodePoints, const int probability)
+                : mTargetCodePoints(std::move(targetCodePoints)),
+                  mProbability(probability) {}
 
         const std::vector<int> *getTargetCodePoints() const {
             return &mTargetCodePoints;
diff --git a/native/jni/src/suggest/core/dictionary/property/word_property.h b/native/jni/src/suggest/core/dictionary/property/word_property.h
index f78380e..4e6febb 100644
--- a/native/jni/src/suggest/core/dictionary/property/word_property.h
+++ b/native/jni/src/suggest/core/dictionary/property/word_property.h
@@ -23,7 +23,6 @@
 #include "jni.h"
 #include "suggest/core/dictionary/property/bigram_property.h"
 #include "suggest/core/dictionary/property/unigram_property.h"
-#include "utils/int_array_view.h"
 
 namespace latinime {
 
@@ -34,9 +33,9 @@
     WordProperty()
             : mCodePoints(), mUnigramProperty(), mBigrams() {}
 
-    WordProperty(const CodePointArrayView codePoints, const UnigramProperty *const unigramProperty,
+    WordProperty(const std::vector<int> &&codePoints, const UnigramProperty *const unigramProperty,
             const std::vector<BigramProperty> *const bigrams)
-            : mCodePoints(codePoints.begin(), codePoints.end()), mUnigramProperty(*unigramProperty),
+            : mCodePoints(std::move(codePoints)), mUnigramProperty(*unigramProperty),
               mBigrams(*bigrams) {}
 
     void outputProperties(JNIEnv *const env, jintArray outCodePoints, jbooleanArray outFlags,
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v402/ver4_patricia_trie_policy.cpp b/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v402/ver4_patricia_trie_policy.cpp
index 3187aa9..f752f89 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v402/ver4_patricia_trie_policy.cpp
+++ b/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v402/ver4_patricia_trie_policy.cpp
@@ -521,15 +521,14 @@
             const int codePointCount = getCodePointsAndReturnCodePointCount(
                     getWordIdFromTerminalPtNodePos(word1TerminalPtNodePos), MAX_WORD_LENGTH,
                     bigramWord1CodePoints);
-            const std::vector<int> word1(bigramWord1CodePoints,
-                    bigramWord1CodePoints + codePointCount);
             const HistoricalInfo *const historicalInfo = bigramEntry.getHistoricalInfo();
             const int probability = bigramEntry.hasHistoricalInfo() ?
                     ForgettingCurveUtils::decodeProbability(
                             bigramEntry.getHistoricalInfo(), mHeaderPolicy) :
                     bigramEntry.getProbability();
-            bigrams.emplace_back(&word1, probability,
-                    historicalInfo->getTimeStamp(), historicalInfo->getLevel(),
+            bigrams.emplace_back(
+                    CodePointArrayView(bigramWord1CodePoints, codePointCount).toVector(),
+                    probability, historicalInfo->getTimeStamp(), historicalInfo->getLevel(),
                     historicalInfo->getCount());
         }
     }
@@ -546,15 +545,16 @@
             int shortcutProbability = NOT_A_PROBABILITY;
             shortcutDictContent->getShortcutEntryAndAdvancePosition(MAX_WORD_LENGTH, shortcutTarget,
                     &shortcutTargetLength, &shortcutProbability, &hasNext, &shortcutPos);
-            const std::vector<int> target(shortcutTarget, shortcutTarget + shortcutTargetLength);
-            shortcuts.emplace_back(&target, shortcutProbability);
+            shortcuts.emplace_back(
+                    CodePointArrayView(shortcutTarget, shortcutTargetLength).toVector(),
+                    shortcutProbability);
         }
     }
     const UnigramProperty unigramProperty(ptNodeParams.representsBeginningOfSentence(),
             ptNodeParams.isNotAWord(), ptNodeParams.isBlacklisted(), ptNodeParams.getProbability(),
             historicalInfo->getTimeStamp(), historicalInfo->getLevel(),
             historicalInfo->getCount(), &shortcuts);
-    return WordProperty(wordCodePoints, &unigramProperty, &bigrams);
+    return WordProperty(wordCodePoints.toVector(), &unigramProperty, &bigrams);
 }
 
 int Ver4PatriciaTriePolicy::getNextWordAndNextToken(const int token, int *const outCodePoints,
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/v2/patricia_trie_policy.cpp b/native/jni/src/suggest/policyimpl/dictionary/structure/v2/patricia_trie_policy.cpp
index 20e0e74..13cf9a5 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/v2/patricia_trie_policy.cpp
+++ b/native/jni/src/suggest/policyimpl/dictionary/structure/v2/patricia_trie_policy.cpp
@@ -449,11 +449,10 @@
             const int word1CodePointCount = getCodePointsAndProbabilityAndReturnCodePointCount(
                     getWordIdFromTerminalPtNodePos(bigramsIt.getBigramPos()), MAX_WORD_LENGTH,
                     bigramWord1CodePoints, &word1Probability);
-            const std::vector<int> word1(bigramWord1CodePoints,
-                    bigramWord1CodePoints + word1CodePointCount);
             const int probability = getProbability(word1Probability, bigramsIt.getProbability());
-            bigrams.emplace_back(&word1, probability,
-                    NOT_A_TIMESTAMP /* timestamp */, 0 /* level */, 0 /* count */);
+            bigrams.emplace_back(
+                    CodePointArrayView(bigramWord1CodePoints, word1CodePointCount).toVector(),
+                    probability, NOT_A_TIMESTAMP /* timestamp */, 0 /* level */, 0 /* count */);
         }
     }
     // Fetch shortcut information.
@@ -469,17 +468,17 @@
             hasNext = ShortcutListReadingUtils::hasNext(shortcutFlags);
             const int shortcutTargetLength = ShortcutListReadingUtils::readShortcutTarget(
                     mBuffer, MAX_WORD_LENGTH, shortcutTargetCodePoints, &shortcutPos);
-            const std::vector<int> shortcutTarget(shortcutTargetCodePoints,
-                    shortcutTargetCodePoints + shortcutTargetLength);
             const int shortcutProbability =
                     ShortcutListReadingUtils::getProbabilityFromFlags(shortcutFlags);
-            shortcuts.emplace_back(&shortcutTarget, shortcutProbability);
+            shortcuts.emplace_back(
+                    CodePointArrayView(shortcutTargetCodePoints, shortcutTargetLength).toVector(),
+                    shortcutProbability);
         }
     }
     const UnigramProperty unigramProperty(ptNodeParams.representsBeginningOfSentence(),
             ptNodeParams.isNotAWord(), ptNodeParams.isBlacklisted(), ptNodeParams.getProbability(),
             NOT_A_TIMESTAMP /* timestamp */, 0 /* level */, 0 /* count */, &shortcuts);
-    return WordProperty(wordCodePoints, &unigramProperty, &bigrams);
+    return WordProperty(wordCodePoints.toVector(), &unigramProperty, &bigrams);
 }
 
 int PatriciaTriePolicy::getNextWordAndNextToken(const int token, int *const outCodePoints,
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/content/language_model_dict_content.cpp b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/content/language_model_dict_content.cpp
index 89094c8..1392302 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/content/language_model_dict_content.cpp
+++ b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/content/language_model_dict_content.cpp
@@ -63,9 +63,14 @@
         int probability = NOT_A_PROBABILITY;
         if (mHasHistoricalInfo) {
             const int rawProbability = ForgettingCurveUtils::decodeProbability(
-                    probabilityEntry.getHistoricalInfo(), headerPolicy)
-                            + ForgettingCurveUtils::getProbabilityBiasForNgram(i + 1 /* n */);
-            probability = std::min(rawProbability, MAX_PROBABILITY);
+                    probabilityEntry.getHistoricalInfo(), headerPolicy);
+            if (rawProbability == NOT_A_PROBABILITY) {
+                // The entry should not be treated as a valid entry.
+                continue;
+            }
+            probability = std::min(rawProbability
+                    + ForgettingCurveUtils::getProbabilityBiasForNgram(i + 1 /* n */),
+                            MAX_PROBABILITY);
         } else {
             probability = probabilityEntry.getProbability();
         }
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_node_reader.cpp b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_node_reader.cpp
index d795239..4110d60 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_node_reader.cpp
+++ b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_node_reader.cpp
@@ -51,26 +51,17 @@
     const int parentPos =
             DynamicPtReadingUtils::getParentPtNodePos(parentPosOffset, headPos);
     int codePoints[MAX_WORD_LENGTH];
-    const int codePonitCount = PatriciaTrieReadingUtils::getCharsAndAdvancePosition(
-            dictBuf, flags, MAX_WORD_LENGTH, mHeaderPolicy->getCodePointTable(), codePoints, &pos);
+    // Code point table is not used for ver4 dictionaries.
+    const int codePointCount = PatriciaTrieReadingUtils::getCharsAndAdvancePosition(
+            dictBuf, flags, MAX_WORD_LENGTH, nullptr /* codePointTable */, codePoints, &pos);
     int terminalIdFieldPos = NOT_A_DICT_POS;
     int terminalId = Ver4DictConstants::NOT_A_TERMINAL_ID;
-    int probability = NOT_A_PROBABILITY;
     if (PatriciaTrieReadingUtils::isTerminal(flags)) {
         terminalIdFieldPos = pos;
         if (usesAdditionalBuffer) {
             terminalIdFieldPos += mBuffer->getOriginalBufferSize();
         }
         terminalId = Ver4PatriciaTrieReadingUtils::getTerminalIdAndAdvancePosition(dictBuf, &pos);
-        // TODO: Quit reading probability here.
-        const ProbabilityEntry probabilityEntry =
-                mLanguageModelDictContent->getProbabilityEntry(terminalId);
-        if (probabilityEntry.hasHistoricalInfo()) {
-            probability = ForgettingCurveUtils::decodeProbability(
-                    probabilityEntry.getHistoricalInfo(), mHeaderPolicy);
-        } else {
-            probability = probabilityEntry.getProbability();
-        }
     }
     int childrenPosFieldPos = pos;
     if (usesAdditionalBuffer) {
@@ -91,8 +82,8 @@
         // The destination position is stored at the same place as the parent position.
         return fetchPtNodeInfoFromBufferAndProcessMovedPtNode(parentPos, newSiblingNodePos);
     } else {
-        return PtNodeParams(headPos, flags, parentPos, codePonitCount, codePoints,
-                terminalIdFieldPos, terminalId, probability, childrenPosFieldPos, childrenPos,
+        return PtNodeParams(headPos, flags, parentPos, codePointCount, codePoints,
+                terminalIdFieldPos, terminalId, NOT_A_PROBABILITY, childrenPosFieldPos, childrenPos,
                 newSiblingNodePos);
     }
 }
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_node_reader.h b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_node_reader.h
index a91ad57..f4df544 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_node_reader.h
+++ b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_node_reader.h
@@ -29,15 +29,12 @@
 
 /*
  * This class is used for helping to read nodes of ver4 patricia trie. This class handles moved
- * node and reads node attributes including probability form language model.
+ * node and reads node attributes.
  */
 class Ver4PatriciaTrieNodeReader : public PtNodeReader {
  public:
-    Ver4PatriciaTrieNodeReader(const BufferWithExtendableBuffer *const buffer,
-            const LanguageModelDictContent *const languageModelDictContent,
-            const HeaderPolicy *const headerPolicy)
-            : mBuffer(buffer), mLanguageModelDictContent(languageModelDictContent),
-              mHeaderPolicy(headerPolicy) {}
+    explicit Ver4PatriciaTrieNodeReader(const BufferWithExtendableBuffer *const buffer)
+            : mBuffer(buffer) {}
 
     ~Ver4PatriciaTrieNodeReader() {}
 
@@ -50,8 +47,6 @@
     DISALLOW_COPY_AND_ASSIGN(Ver4PatriciaTrieNodeReader);
 
     const BufferWithExtendableBuffer *const mBuffer;
-    const LanguageModelDictContent *const mLanguageModelDictContent;
-    const HeaderPolicy *const mHeaderPolicy;
 
     const PtNodeParams fetchPtNodeInfoFromBufferAndProcessMovedPtNode(const int ptNodePos,
             const int siblingNodePos) const;
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_policy.cpp b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_policy.cpp
index 0349ba4..0f06964 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_policy.cpp
+++ b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_policy.cpp
@@ -56,13 +56,7 @@
         if (!ptNodeParams.isValid()) {
             break;
         }
-        bool isTerminal = ptNodeParams.isTerminal() && !ptNodeParams.isDeleted();
-        if (isTerminal && mHeaderPolicy->isDecayingDict()) {
-            // A DecayingDict may have a terminal PtNode that has a terminal DicNode whose
-            // probability is NOT_A_PROBABILITY. In such case, we don't want to treat it as a
-            // valid terminal DicNode.
-            isTerminal = ptNodeParams.getProbability() != NOT_A_PROBABILITY;
-        }
+        const bool isTerminal = ptNodeParams.isTerminal() && !ptNodeParams.isDeleted();
         const int wordId = isTerminal ? ptNodeParams.getTerminalId() : NOT_A_WORD_ID;
         childDicNodes->pushLeavingChild(dicNode, ptNodeParams.getChildrenPos(),
                 wordId, ptNodeParams.getCodePointArrayView());
@@ -464,15 +458,13 @@
             prevWordIds)) {
         const int codePointCount = getCodePointsAndReturnCodePointCount(entry.getWordId(),
                 MAX_WORD_LENGTH, bigramWord1CodePoints);
-        const std::vector<int> word1(bigramWord1CodePoints,
-                bigramWord1CodePoints + codePointCount);
         const ProbabilityEntry probabilityEntry = entry.getProbabilityEntry();
         const HistoricalInfo *const historicalInfo = probabilityEntry.getHistoricalInfo();
         const int probability = probabilityEntry.hasHistoricalInfo() ?
                 ForgettingCurveUtils::decodeProbability(historicalInfo, mHeaderPolicy) :
                 probabilityEntry.getProbability();
-        bigrams.emplace_back(&word1, probability,
-                historicalInfo->getTimeStamp(), historicalInfo->getLevel(),
+        bigrams.emplace_back(CodePointArrayView(bigramWord1CodePoints, codePointCount).toVector(),
+                probability, historicalInfo->getTimeStamp(), historicalInfo->getLevel(),
                 historicalInfo->getCount());
     }
     // Fetch shortcut information.
@@ -488,15 +480,16 @@
             int shortcutProbability = NOT_A_PROBABILITY;
             shortcutDictContent->getShortcutEntryAndAdvancePosition(MAX_WORD_LENGTH, shortcutTarget,
                     &shortcutTargetLength, &shortcutProbability, &hasNext, &shortcutPos);
-            const std::vector<int> target(shortcutTarget, shortcutTarget + shortcutTargetLength);
-            shortcuts.emplace_back(&target, shortcutProbability);
+            shortcuts.emplace_back(
+                    CodePointArrayView(shortcutTarget, shortcutTargetLength).toVector(),
+                    shortcutProbability);
         }
     }
     const UnigramProperty unigramProperty(probabilityEntry.representsBeginningOfSentence(),
             probabilityEntry.isNotAWord(), probabilityEntry.isBlacklisted(),
             probabilityEntry.getProbability(), historicalInfo->getTimeStamp(),
             historicalInfo->getLevel(), historicalInfo->getCount(), &shortcuts);
-    return WordProperty(wordCodePoints, &unigramProperty, &bigrams);
+    return WordProperty(wordCodePoints.toVector(), &unigramProperty, &bigrams);
 }
 
 int Ver4PatriciaTriePolicy::getNextWordAndNextToken(const int token, int *const outCodePoints,
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_policy.h b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_policy.h
index 758f8da..c9bde2c 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_policy.h
+++ b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_policy.h
@@ -45,8 +45,7 @@
               mDictBuffer(mBuffers->getWritableTrieBuffer()),
               mShortcutPolicy(mBuffers->getMutableShortcutDictContent(),
                       mBuffers->getTerminalPositionLookupTable()),
-              mNodeReader(mDictBuffer, mBuffers->getLanguageModelDictContent(), mHeaderPolicy),
-              mPtNodeArrayReader(mDictBuffer),
+              mNodeReader(mDictBuffer), mPtNodeArrayReader(mDictBuffer),
               mNodeWriter(mDictBuffer, mBuffers.get(), mHeaderPolicy, &mNodeReader,
                       &mPtNodeArrayReader, &mShortcutPolicy),
               mUpdatingHelper(mDictBuffer, &mNodeReader, &mNodeWriter),
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_writing_helper.cpp b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_writing_helper.cpp
index 63e43a5..442abad 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_writing_helper.cpp
+++ b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_writing_helper.cpp
@@ -73,8 +73,7 @@
 bool Ver4PatriciaTrieWritingHelper::runGC(const int rootPtNodeArrayPos,
         const HeaderPolicy *const headerPolicy, Ver4DictBuffers *const buffersToWrite,
         int *const outUnigramCount, int *const outBigramCount) {
-    Ver4PatriciaTrieNodeReader ptNodeReader(mBuffers->getTrieBuffer(),
-            mBuffers->getLanguageModelDictContent(), headerPolicy);
+    Ver4PatriciaTrieNodeReader ptNodeReader(mBuffers->getTrieBuffer());
     Ver4PtNodeArrayReader ptNodeArrayReader(mBuffers->getTrieBuffer());
     Ver4ShortcutListPolicy shortcutPolicy(mBuffers->getMutableShortcutDictContent(),
             mBuffers->getTerminalPositionLookupTable());
@@ -137,8 +136,7 @@
     }
 
     // Create policy instances for the GCed dictionary.
-    Ver4PatriciaTrieNodeReader newPtNodeReader(buffersToWrite->getTrieBuffer(),
-            buffersToWrite->getLanguageModelDictContent(), headerPolicy);
+    Ver4PatriciaTrieNodeReader newPtNodeReader(buffersToWrite->getTrieBuffer());
     Ver4PtNodeArrayReader newPtNodeArrayreader(buffersToWrite->getTrieBuffer());
     Ver4ShortcutListPolicy newShortcutPolicy(buffersToWrite->getMutableShortcutDictContent(),
             buffersToWrite->getTerminalPositionLookupTable());
diff --git a/native/jni/src/utils/int_array_view.h b/native/jni/src/utils/int_array_view.h
index f3a8589..4083731 100644
--- a/native/jni/src/utils/int_array_view.h
+++ b/native/jni/src/utils/int_array_view.h
@@ -129,6 +129,10 @@
         return mPtr[mSize - 1];
     }
 
+    AK_FORCE_INLINE std::vector<int> toVector() const {
+        return std::vector<int>(begin(), end());
+    }
+
  private:
     DISALLOW_ASSIGNMENT_OPERATOR(IntArrayView);
 
diff --git a/native/jni/tests/utils/int_array_view_test.cpp b/native/jni/tests/utils/int_array_view_test.cpp
index 487bd04..4757a41 100644
--- a/native/jni/tests/utils/int_array_view_test.cpp
+++ b/native/jni/tests/utils/int_array_view_test.cpp
@@ -144,5 +144,12 @@
     EXPECT_EQ(10, intArrayView.skip(6).lastOrDefault(10));
 }
 
+TEST(IntArrayViewTest, TestToVector) {
+    const std::vector<int> intVector = {3, 2, 1, 0, -1, -2};
+    IntArrayView intArrayView(intVector);
+    EXPECT_EQ(intVector, intArrayView.toVector());
+    EXPECT_EQ(std::vector<int>(), CodePointArrayView().toVector());
+}
+
 }  // namespace
 }  // namespace latinime