Remove computed GOTO

This commit is contained in:
John Keiser 2020-07-27 18:18:35 -07:00
parent 2f67dab2b6
commit 8e69103822
3 changed files with 24 additions and 44 deletions

View File

@ -20,8 +20,8 @@ class dom_parser_implementation final : public internal::dom_parser_implementati
public:
/** Tape location of each open { or [ */
std::unique_ptr<scope_descriptor[]> containing_scope{};
/** Return address of each open { or [ */
std::unique_ptr<ret_address_t[]> ret_address{};
/** Whether each open container is a [ or { */
std::unique_ptr<bool[]> is_array{};
/** Buffer passed to stage 1 */
const uint8_t *buf{};
/** Length passed to stage 1 */

View File

@ -8,9 +8,9 @@ namespace allocate {
//
really_inline error_code set_max_depth(dom_parser_implementation &parser, size_t max_depth) {
parser.containing_scope.reset(new (std::nothrow) scope_descriptor[max_depth]);
parser.ret_address.reset(new (std::nothrow) ret_address_t[max_depth]);
parser.is_array.reset(new (std::nothrow) bool[max_depth]);
if (!parser.ret_address || !parser.containing_scope) {
if (!parser.is_array || !parser.containing_scope) {
return MEMALLOC;
}
return SUCCESS;

View File

@ -12,27 +12,6 @@ namespace { // Make everything here private
namespace SIMDJSON_IMPLEMENTATION {
namespace stage2 {
#ifdef SIMDJSON_USE_COMPUTED_GOTO
#define INIT_ADDRESSES() { &&array_continue, &&finish, &&object_continue }
#define CONTINUE(address) { goto *(address); }
#else // SIMDJSON_USE_COMPUTED_GOTO
#define INIT_ADDRESSES() { 0, 1, 2 };
#define CONTINUE(address) \
{ \
switch(address) { \
case 0: goto array_continue; \
case 1: goto finish; \
case 2: goto object_continue; \
} \
}
#endif // SIMDJSON_USE_COMPUTED_GOTO
struct unified_machine_addresses {
ret_address_t array_continue;
ret_address_t finish;
ret_address_t object_continue;
};
struct structural_parser : structural_iterator {
/** Lets you append to the tape */
tape_writer tape;
@ -48,30 +27,30 @@ struct structural_parser : structural_iterator {
current_string_buf_loc{parser.doc->string_buf.get()} {
}
WARN_UNUSED really_inline bool start_scope(ret_address_t continue_state) {
WARN_UNUSED really_inline bool start_scope(bool parent_is_array) {
parser.containing_scope[depth].tape_index = next_tape_index();
parser.containing_scope[depth].count = 0;
tape.skip(); // We don't actually *write* the start element until the end.
parser.ret_address[depth] = continue_state;
parser.is_array[depth] = parent_is_array;
depth++;
bool exceeded_max_depth = depth >= parser.max_depth();
if (exceeded_max_depth) { log_error("Exceeded max depth!"); }
return exceeded_max_depth;
}
WARN_UNUSED really_inline bool start_document(ret_address_t continue_state) {
WARN_UNUSED really_inline bool start_document() {
log_start_value("document");
return start_scope(continue_state);
return start_scope(false);
}
WARN_UNUSED really_inline bool start_object(ret_address_t continue_state) {
WARN_UNUSED really_inline bool start_object(bool parent_is_array) {
log_start_value("object");
return start_scope(continue_state);
return start_scope(parent_is_array);
}
WARN_UNUSED really_inline bool start_array(ret_address_t continue_state) {
WARN_UNUSED really_inline bool start_array(bool parent_is_array) {
log_start_value("array");
return start_scope(continue_state);
return start_scope(parent_is_array);
}
// this function is responsible for annotating the start of the scope
@ -277,7 +256,7 @@ struct structural_parser : structural_iterator {
parser.error = UNINITIALIZED;
}
WARN_UNUSED really_inline error_code start(ret_address_t finish_state) {
WARN_UNUSED really_inline error_code start() {
// If there are no structurals left, return EMPTY
if (at_end(parser.n_structural_indexes)) {
return parser.error = EMPTY;
@ -285,7 +264,7 @@ struct structural_parser : structural_iterator {
init();
// Push the root scope (there is always at least one scope)
if (start_document(finish_state)) {
if (start_document()) {
return parser.error = DEPTH_ERROR;
}
return SUCCESS;
@ -317,9 +296,8 @@ struct structural_parser : structural_iterator {
template<bool STREAMING>
WARN_UNUSED static error_code parse_structurals(dom_parser_implementation &dom_parser, dom::document &doc) noexcept {
dom_parser.doc = &doc;
static constexpr stage2::unified_machine_addresses addresses = INIT_ADDRESSES();
stage2::structural_parser parser(dom_parser, STREAMING ? dom_parser.next_structural_index : 0);
error_code result = parser.start(addresses.finish);
error_code result = parser.start();
if (result) { return result; }
//
@ -327,10 +305,10 @@ WARN_UNUSED static error_code parse_structurals(dom_parser_implementation &dom_p
//
switch (parser.current_char()) {
case '{':
if ( parser.start_object(addresses.finish) ) { goto error; };
if ( parser.start_object(false) ) { goto error; };
goto object_begin;
case '[':
if ( parser.start_array(addresses.finish) ) { goto error; }
if ( parser.start_array(false) ) { goto error; }
// Make sure the outer array is closed before continuing; otherwise, there are ways we could get
// into memory corruption. See https://github.com/simdjson/simdjson/issues/906
if (!STREAMING) {
@ -377,8 +355,8 @@ object_begin:
object_key_state:
if (parser.advance_char() != ':' ) { parser.log_error("Missing colon after key in object"); goto error; }
switch (parser.advance_char()) {
case '{': if ( parser.start_object(addresses.object_continue) ) { goto error; } else { goto object_begin; }
case '[': if ( parser.start_array(addresses.object_continue) ) { goto error; } else { goto array_begin; }
case '{': if ( parser.start_object(false) ) { goto error; } else { goto object_begin; }
case '[': if ( parser.start_array(false) ) { goto error; } else { goto array_begin; }
case '"': if ( parser.parse_string() ) { goto error; }; break;
case 't': if ( parser.parse_true_atom() ) { goto error; }; break;
case 'f': if ( parser.parse_false_atom() ) { goto error; }; break;
@ -408,7 +386,9 @@ object_continue:
}
scope_end:
CONTINUE( parser.parser.ret_address[parser.depth] );
if (parser.depth == 1) { goto finish; }
if (parser.parser.is_array[parser.depth]) { goto array_continue; }
goto object_continue;
//
// Array parser states
@ -423,8 +403,8 @@ array_begin:
main_array_switch:
switch (parser.advance_char()) {
case '{': if ( parser.start_object(addresses.array_continue) ) { goto error; } else { goto object_begin; }
case '[': if ( parser.start_array(addresses.array_continue) ) { goto error; } else { goto array_begin; }
case '{': if ( parser.start_object(true) ) { goto error; } else { goto object_begin; }
case '[': if ( parser.start_array(true) ) { goto error; } else { goto array_begin; }
case '"': if ( parser.parse_string() ) { goto error; }; break;
case 't': if ( parser.parse_true_atom() ) { goto error; }; break;
case 'f': if ( parser.parse_false_atom() ) { goto error; }; break;