One weird trick: set a bogus error value in the parser impl

This makes us faster under both gcc and clang somehow.
This commit is contained in:
John Keiser 2020-06-01 12:14:09 -07:00
parent 1aab4752e2
commit 3d22a2d845
3 changed files with 20 additions and 16 deletions

View File

@ -136,6 +136,9 @@ public:
/** Return address of each open { or [ */ /** Return address of each open { or [ */
std::unique_ptr<internal::ret_address[]> ret_address{}; std::unique_ptr<internal::ret_address[]> ret_address{};
/** Error code, used ENTIRELY to make gcc not be slower than before. Not actually consumed. */
error_code error{UNINITIALIZED};
/** /**
* The largest document this parser can support without reallocating. * The largest document this parser can support without reallocating.
* *

View File

@ -12,7 +12,7 @@ struct streaming_structural_parser: structural_parser {
advance_char(); advance_char();
// Push the root scope (there is always at least one scope) // Push the root scope (there is always at least one scope)
if (start_document(finish_parser)) { if (start_document(finish_parser)) {
return DEPTH_ERROR; return parser.error = DEPTH_ERROR;
} }
return SUCCESS; return SUCCESS;
} }
@ -21,16 +21,16 @@ struct streaming_structural_parser: structural_parser {
WARN_UNUSED really_inline error_code finish() { WARN_UNUSED really_inline error_code finish() {
if ( structurals.past_end(parser.n_structural_indexes) ) { if ( structurals.past_end(parser.n_structural_indexes) ) {
log_error("IMPOSSIBLE: past the end of the JSON!"); log_error("IMPOSSIBLE: past the end of the JSON!");
return TAPE_ERROR; return parser.error = TAPE_ERROR;
} }
end_document(); end_document();
if (depth != 0) { if (depth != 0) {
log_error("Unclosed objects or arrays!"); log_error("Unclosed objects or arrays!");
return TAPE_ERROR; return parser.error = TAPE_ERROR;
} }
if (parser.containing_scope[depth].tape_index != 0) { if (parser.containing_scope[depth].tape_index != 0) {
log_error("IMPOSSIBLE: root scope tape index did not start at 0!"); log_error("IMPOSSIBLE: root scope tape index did not start at 0!");
return TAPE_ERROR; return parser.error = TAPE_ERROR;
} }
bool finished = structurals.at_end(parser.n_structural_indexes); bool finished = structurals.at_end(parser.n_structural_indexes);
if (!finished) { log_value("(and has more)"); } if (!finished) { log_value("(and has more)"); }

View File

@ -272,16 +272,16 @@ struct structural_parser {
// the string might not be NULL terminated. // the string might not be NULL terminated.
if ( !structurals.at_end(parser.n_structural_indexes) ) { if ( !structurals.at_end(parser.n_structural_indexes) ) {
log_error("More than one JSON value at the root of the document, or extra characters at the end of the JSON!"); log_error("More than one JSON value at the root of the document, or extra characters at the end of the JSON!");
return TAPE_ERROR; return parser.error = TAPE_ERROR;
} }
end_document(); end_document();
if (depth != 0) { if (depth != 0) {
log_error("Unclosed objects or arrays!"); log_error("Unclosed objects or arrays!");
return TAPE_ERROR; return parser.error = TAPE_ERROR;
} }
if (parser.containing_scope[depth].tape_index != 0) { if (parser.containing_scope[depth].tape_index != 0) {
log_error("IMPOSSIBLE: root scope tape index did not start at 0!"); log_error("IMPOSSIBLE: root scope tape index did not start at 0!");
return TAPE_ERROR; return parser.error = TAPE_ERROR;
} }
return SUCCESS; return SUCCESS;
@ -299,11 +299,11 @@ struct structural_parser {
* carefully, * carefully,
* all without any added cost. */ * all without any added cost. */
if (depth >= parser.max_depth()) { if (depth >= parser.max_depth()) {
return DEPTH_ERROR; return parser.error = DEPTH_ERROR;
} }
switch (structurals.current_char()) { switch (structurals.current_char()) {
case '"': case '"':
return STRING_ERROR; return parser.error = STRING_ERROR;
case '0': case '0':
case '1': case '1':
case '2': case '2':
@ -315,34 +315,35 @@ struct structural_parser {
case '8': case '8':
case '9': case '9':
case '-': case '-':
return NUMBER_ERROR; return parser.error = NUMBER_ERROR;
case 't': case 't':
return T_ATOM_ERROR; return parser.error = T_ATOM_ERROR;
case 'n': case 'n':
return N_ATOM_ERROR; return parser.error = N_ATOM_ERROR;
case 'f': case 'f':
return F_ATOM_ERROR; return parser.error = F_ATOM_ERROR;
default: default:
return TAPE_ERROR; return parser.error = TAPE_ERROR;
} }
} }
really_inline void init() { really_inline void init() {
current_string_buf_loc = parser.doc->string_buf.get(); current_string_buf_loc = parser.doc->string_buf.get();
parser.current_loc = 0; parser.current_loc = 0;
parser.error = UNINITIALIZED;
} }
WARN_UNUSED really_inline error_code start(size_t len, ret_address finish_state) { WARN_UNUSED really_inline error_code start(size_t len, ret_address finish_state) {
log_start(); log_start();
init(); // sets is_valid to false init(); // sets is_valid to false
if (len > parser.capacity()) { if (len > parser.capacity()) {
return CAPACITY; return parser.error = CAPACITY;
} }
// Advance to the first character as soon as possible // Advance to the first character as soon as possible
structurals.advance_char(); structurals.advance_char();
// Push the root scope (there is always at least one scope) // Push the root scope (there is always at least one scope)
if (start_document(finish_state)) { if (start_document(finish_state)) {
return DEPTH_ERROR; return parser.error = DEPTH_ERROR;
} }
return SUCCESS; return SUCCESS;
} }