diff options
Diffstat (limited to 'erts/emulator/beam/beam_file.c')
-rw-r--r-- | erts/emulator/beam/beam_file.c | 120 |
1 files changed, 84 insertions, 36 deletions
diff --git a/erts/emulator/beam/beam_file.c b/erts/emulator/beam/beam_file.c index 0c7bdfbec2..d210d0fc16 100644 --- a/erts/emulator/beam/beam_file.c +++ b/erts/emulator/beam/beam_file.c @@ -1,7 +1,7 @@ /* * %CopyrightBegin% * - * Copyright Ericsson AB 2020-2022. All Rights Reserved. + * Copyright Ericsson AB 2020-2023. 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. @@ -527,7 +527,7 @@ static int parse_line_chunk(BeamFile *beam, IFF_Chunk *chunk) { hp = name_heap; name = erts_atom_to_string(&hp, beam->module, suffix); - lines->names[0] = beamfile_add_literal(beam, name); + lines->names[0] = beamfile_add_literal(beam, name, 1); for (i = 1; i < name_count; i++) { Uint num_chars, num_built, num_eaten; @@ -563,7 +563,7 @@ static int parse_line_chunk(BeamFile *beam, IFF_Chunk *chunk) { ASSERT(num_built == num_chars); ASSERT(num_eaten == name_length); - lines->names[i] = beamfile_add_literal(beam, name); + lines->names[i] = beamfile_add_literal(beam, name, 1); if (name_heap != default_name_buf) { erts_free(ERTS_ALC_T_LOADER_TMP, name_heap); @@ -595,30 +595,52 @@ static void init_fallback_type_table(BeamFile *beam) { types->fallback = 1; types->entries[0].type_union = BEAM_TYPE_ANY; - types->entries[0].min = 0; - types->entries[0].max = -1; + types->entries[0].min = MAX_SMALL + 1; + types->entries[0].max = MIN_SMALL - 1; } -static int parse_type_chunk(BeamFile *beam, IFF_Chunk *chunk) { +static int parse_type_chunk_otp_25(BeamFile *beam, BeamReader *p_reader) { BeamFile_TypeTable *types; - BeamReader reader; - Sint32 version, count; + Sint32 count; int i; - beamreader_init(chunk->data, chunk->size, &reader); + types = &beam->types; + ASSERT(types->entries == NULL); - LoadAssert(beamreader_read_i32(&reader, &version)); - if (version != BEAM_TYPES_VERSION) { - /* Incompatible type format. */ - init_fallback_type_table(beam); - return 1; + LoadAssert(beamreader_read_i32(p_reader, &count)); + LoadAssert(CHECK_ITEM_COUNT(count, 0, sizeof(types->entries[0]))); + LoadAssert(count >= 1); + + types->entries = erts_alloc(ERTS_ALC_T_PREPARED_CODE, + count * sizeof(types->entries[0])); + types->count = count; + types->fallback = 0; + + for (i = 0; i < count; i++) { + const byte *type_data; + + LoadAssert(beamreader_read_bytes(p_reader, 18, &type_data)); + LoadAssert(beam_types_decode_otp_25(type_data, 18, &types->entries[i])); } + /* The first entry MUST be the "any type." */ + LoadAssert(types->entries[0].type_union == BEAM_TYPE_ANY); + LoadAssert(types->entries[0].min > types->entries[0].max); + + return 1; +} + +static int parse_type_chunk_otp_26(BeamFile *beam, BeamReader *p_reader) { + BeamFile_TypeTable *types; + + Sint32 count; + int i; + types = &beam->types; ASSERT(types->entries == NULL); - LoadAssert(beamreader_read_i32(&reader, &count)); + LoadAssert(beamreader_read_i32(p_reader, &count)); LoadAssert(CHECK_ITEM_COUNT(count, 0, sizeof(types->entries[0]))); LoadAssert(count >= 1); @@ -629,9 +651,13 @@ static int parse_type_chunk(BeamFile *beam, IFF_Chunk *chunk) { for (i = 0; i < count; i++) { const byte *type_data; + int extra; - LoadAssert(beamreader_read_bytes(&reader, 18, &type_data)); - LoadAssert(beam_types_decode(type_data, 18, &types->entries[i])); + LoadAssert(beamreader_read_bytes(p_reader, 2, &type_data)); + extra = beam_types_decode_type_otp_26(type_data, &types->entries[i]); + LoadAssert(extra >= 0); + LoadAssert(beamreader_read_bytes(p_reader, extra, &type_data)); + beam_types_decode_extra_otp_26(type_data, &types->entries[i]); } /* The first entry MUST be the "any type." */ @@ -641,6 +667,25 @@ static int parse_type_chunk(BeamFile *beam, IFF_Chunk *chunk) { return 1; } +static int parse_type_chunk(BeamFile *beam, IFF_Chunk *chunk) { + BeamReader reader; + Sint32 version; + + beamreader_init(chunk->data, chunk->size, &reader); + + LoadAssert(beamreader_read_i32(&reader, &version)); + switch (version) { + case 1: /* OTP 25 */ + return parse_type_chunk_otp_25(beam, &reader); + case BEAM_TYPES_VERSION: /* OTP 26 */ + return parse_type_chunk_otp_26(beam, &reader); + default: + /* Incompatible type format. */ + init_fallback_type_table(beam); + return 1; + } +} + static ErlHeapFragment *new_literal_fragment(Uint size) { ErlHeapFragment *bp; @@ -1134,7 +1179,7 @@ void beamfile_free(BeamFile *beam) { } } -Sint beamfile_add_literal(BeamFile *beam, Eterm term) { +Sint beamfile_add_literal(BeamFile *beam, Eterm term, int deduplicate) { BeamFile_LiteralTable *literals; BeamFile_LiteralEntry *entries; @@ -1146,22 +1191,17 @@ Sint beamfile_add_literal(BeamFile *beam, Eterm term) { literals = &beam->dynamic_literals; entries = literals->entries; - if (entries == NULL) { - literals->allocated = 32; - - entries = erts_alloc(ERTS_ALC_T_PREPARED_CODE, - literals->allocated * sizeof(*entries)); - - literals->entries = entries; - } else { - /* Return a matching index if this literal already exists. We search - * backwards since duplicates tend to be used close to one another, - * and skip searching static literals as the chances of overlap are - * pretty slim. */ - for (i = literals->count - 1; i >= 0; i--) { - if (EQ(term, entries[i].value)) { - /* Dynamic literal indexes are negative, starting at -1 */ - return ~i; + if (entries != NULL) { + if (deduplicate) { + /* Return a matching index if this literal already exists. + * We search backwards since duplicates tend to be used close to + * one another, and skip searching static literals as the chances + * of overlap are pretty slim. */ + for (i = literals->count - 1; i >= 0; i--) { + if (EQ(term, entries[i].value)) { + /* Dynamic literal indexes are negative, starting at -1 */ + return ~i; + } } } @@ -1173,6 +1213,13 @@ Sint beamfile_add_literal(BeamFile *beam, Eterm term) { literals->entries = entries; } + } else { + literals->allocated = 32; + + entries = erts_alloc(ERTS_ALC_T_PREPARED_CODE, + literals->allocated * sizeof(*entries)); + + literals->entries = entries; } term_size = size_object(term); @@ -1271,7 +1318,7 @@ int iff_read_chunk(IFF_File *iff, Uint id, IFF_Chunk *chunk) return read_beam_chunks(iff, 1, &id, chunk); } -void beamfile_init() { +void beamfile_init(void) { Eterm suffix; Eterm *hp; @@ -1419,7 +1466,8 @@ static int marshal_integer(BeamCodeReader *code_reader, TaggedNumber *value) { value->tag = TAG_q; value->size = 0; - value->word_value = beamfile_add_literal(code_reader->file, term); + value->word_value = beamfile_add_literal(code_reader->file, + term, 1); } else { /* Result doesn't fit into a bignum. */ value->tag = TAG_o; |