// -*- c -*-
//
// %CopyrightBegin%
//
// Copyright Ericsson AB 2017. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// %CopyrightEnd%
//
ensure_map(Map) {
if (is_not_map($Map)) {
c_p->freason = BADMAP;
c_p->fvalue = $Map;
$FAIL_BODY();
}
}
new_map(Dst, Live, N) {
Eterm res;
HEAVY_SWAPOUT;
res = erts_gc_new_map(c_p, reg, $Live, $N, $NEXT_INSTRUCTION);
HEAVY_SWAPIN;
$REFRESH_GEN_DEST();
$Dst = res;
$NEXT($NEXT_INSTRUCTION+$N);
}
i_new_small_map_lit(Dst, Live, Keys) {
Eterm res;
Uint n;
Eterm keys = $Keys;
HEAVY_SWAPOUT;
res = erts_gc_new_small_map_lit(c_p, reg, keys, $Live, $NEXT_INSTRUCTION);
HEAVY_SWAPIN;
$REFRESH_GEN_DEST();
$Dst = res;
n = arityval(*tuple_val(keys));
$NEXT($NEXT_INSTRUCTION+n);
}
i_get_map_element(Fail, Src, Key, Dst) {
Eterm res = get_map_element($Src, $Key);
if (is_non_value(res)) {
$FAIL($Fail);
}
$Dst = res;
}
i_get_map_element_hash(Fail, Src, Key, Hx, Dst) {
Eterm res = get_map_element_hash($Src, $Key, $Hx);
if (is_non_value(res)) {
$FAIL($Fail);
}
$Dst = res;
}
i_get_map_elements(Fail, Src, N) {
Eterm map;
BeamInstr *fs;
Uint sz, n;
map = $Src;
/* This instruction assumes Arg1 is a map,
* i.e. that it follows a test is_map if needed.
*/
n = (Uint)$N / 3;
fs = $NEXT_INSTRUCTION;
if (is_flatmap(map)) {
flatmap_t *mp;
Eterm *ks;
Eterm *vs;
mp = (flatmap_t *)flatmap_val(map);
sz = flatmap_get_size(mp);
if (sz == 0) {
$FAIL($Fail);
}
ks = flatmap_get_keys(mp);
vs = flatmap_get_values(mp);
while(sz) {
if (EQ((Eterm) fs[0], *ks)) {
PUT_TERM_REG(*vs, fs[1]);
n--;
fs += 3;
/* no more values to fetch, we are done */
if (n == 0) {
$NEXT(fs);
}
}
ks++, sz--, vs++;
}
$FAIL($Fail);
} else {
const Eterm *v;
Uint32 hx;
ASSERT(is_hashmap(map));
while(n--) {
hx = fs[2];
ASSERT(hx == hashmap_make_hash((Eterm)fs[0]));
if ((v = erts_hashmap_get(hx, (Eterm)fs[0], map)) == NULL) {
$FAIL($Fail);
}
PUT_TERM_REG(*v, fs[1]);
fs += 3;
}
$NEXT(fs);
}
}
update_map_assoc(Src, Dst, Live, N) {
Eterm res;
Uint live = $Live;
reg[live] = $Src;
HEAVY_SWAPOUT;
res = erts_gc_update_map_assoc(c_p, reg, live, $N, $NEXT_INSTRUCTION);
HEAVY_SWAPIN;
ASSERT(is_value(res));
$REFRESH_GEN_DEST();
$Dst = res;
$NEXT($NEXT_INSTRUCTION+$N);
}
update_map_exact(Fail, Src, Dst, Live, N) {
Eterm res;
Uint live = $Live;
reg[live] = $Src;
HEAVY_SWAPOUT;
res = erts_gc_update_map_exact(c_p, reg, live, $N, $NEXT_INSTRUCTION);
HEAVY_SWAPIN;
if (is_value(res)) {
$REFRESH_GEN_DEST();
$Dst = res;
$NEXT($NEXT_INSTRUCTION+$N);
} else {
$FAIL_HEAD_OR_BODY($Fail);
}
}