static value_t heap_object_identity_compare(value_t a, value_t b, cycle_detector_t *detector) { CHECK_DOMAIN(vdHeapObject, a); CHECK_DOMAIN(vdHeapObject, b); // Fast case when a and b are the same object. if (is_same_value(a, b)) return yes(); heap_object_family_t a_family = get_heap_object_family(a); heap_object_family_t b_family = get_heap_object_family(b); if (a_family != b_family) return no(); family_behavior_t *behavior = get_heap_object_family_behavior(a); return (behavior->identity_compare)(a, b, detector); }
static value_t custom_tagged_ordering_compare(value_t a, value_t b) { CHECK_DOMAIN(vdCustomTagged, a); CHECK_DOMAIN(vdCustomTagged, b); custom_tagged_phylum_t a_phylum = get_custom_tagged_phylum(a); custom_tagged_phylum_t b_phylum = get_custom_tagged_phylum(b); if (a_phylum != b_phylum) return compare_signed_integers(a_phylum, b_phylum); phylum_behavior_t *behavior = get_custom_tagged_phylum_behavior(a_phylum); value_t (*ordering_compare)(value_t a, value_t b) = behavior->ordering_compare; if (ordering_compare == NULL) { return unordered(); } else { return ordering_compare(a, b); } }
static value_t integer_transient_identity_hash(value_t self, hash_stream_t *stream) { CHECK_DOMAIN(vdInteger, self); hash_stream_write_tags(stream, vdInteger, __ofUnknown__); hash_stream_write_int64(stream, get_integer_value(self)); return success(); }
// Checks whether to fire the next barrier on the way to the given destination. // If there is a barrier to fire, fire it. Returns false iff a barrier was fired, // true if we've arrived at the destination. static bool maybe_fire_next_barrier(code_cache_t *cache, frame_t *frame, runtime_t *runtime, value_t stack, value_t destination) { CHECK_DOMAIN(vdDerivedObject, destination); value_t next_barrier = get_stack_top_barrier(stack); if (is_same_value(next_barrier, destination)) { // We've arrived. return true; } // Grab the next barrier's handler. value_t payload = get_barrier_state_payload(next_barrier); value_t previous = get_barrier_state_previous(next_barrier); // Unhook the barrier from the barrier stack. set_stack_top_barrier(stack, previous); // Fire the exit action for the handler object. if (in_genus(dgEnsureSection, next_barrier)) { // Pop any previous state off the stack. If we've executed any // code shards before the first will be the result from the shard // the second will be the shard itself. frame_pop_value(frame); frame_pop_value(frame); // Push the shard onto the stack as the subject since we may need it // to refract access to outer variables. frame_push_value(frame, next_barrier); value_t argmap = ROOT(runtime, array_of_zero); value_t code_block = payload; push_stack_frame(runtime, stack, frame, get_code_block_high_water_mark(code_block), argmap); frame_set_code_block(frame, code_block); code_cache_refresh(cache, frame); } else { on_derived_object_exit(next_barrier); } return false; }
static value_t object_ordering_compare(value_t a, value_t b) { CHECK_DOMAIN(vdHeapObject, a); CHECK_DOMAIN(vdHeapObject, b); heap_object_family_t a_family = get_heap_object_family(a); heap_object_family_t b_family = get_heap_object_family(b); if (a_family != b_family) // This may cause us to return a valid result even when a and b are not // comparable. return compare_signed_integers(a_family, b_family); family_behavior_t *behavior = get_heap_object_family_behavior(a); value_t (*ordering_compare)(value_t a, value_t b) = behavior->ordering_compare; if (ordering_compare == NULL) { return unordered(); } else { return ordering_compare(a, b); } }
static value_t custom_tagged_transient_identity_hash(value_t self, hash_stream_t *stream) { CHECK_DOMAIN(vdCustomTagged, self); hash_stream_write_tags(stream, vdCustomTagged, __ofUnknown__); hash_stream_write_int64(stream, get_custom_tagged_phylum(self)); hash_stream_write_int64(stream, get_custom_tagged_payload(self)); return success(); }
value_t finalize_heap_object(value_t garbage) { CHECK_DOMAIN(vdHeapObject, garbage); value_t header = get_heap_object_header(garbage); CHECK_FALSE("finalizing live object", in_domain(vdMovedObject, header)); family_behavior_t *behavior = get_species_family_behavior(header); garbage_value_t wrapper = {garbage}; CHECK_FALSE("finalizing object without finalizer", behavior->finalize == NULL); return (behavior->finalize(wrapper)); }
void get_heap_object_layout(value_t self, heap_object_layout_t *layout_out) { // This has to work during gc so some of the normal behavior checks are // disabled. CHECK_DOMAIN(vdHeapObject, self); // We only get the layout of objects that have already been moved so this // gives a proper species. value_t species = get_heap_object_species(self); // The species itself may have been moved but in any its memory will still be // intact enough that we can get the behavior out. family_behavior_t *behavior = get_species_family_behavior(species); (behavior->get_heap_object_layout)(self, layout_out); }
phylum_behavior_t *get_custom_tagged_behavior(value_t value) { CHECK_DOMAIN(vdCustomTagged, value); custom_tagged_phylum_t phylum = get_custom_tagged_phylum(value); return get_custom_tagged_phylum_behavior(phylum); }
void on_derived_object_exit(value_t self) { CHECK_DOMAIN(vdDerivedObject, self); genus_descriptor_t *descriptor = get_derived_object_descriptor(self); CHECK_TRUE("derived object not scoped", descriptor->on_scope_exit != NULL); (descriptor->on_scope_exit)(self); }
static void derived_object_print_on(value_t value, print_on_context_t *context) { CHECK_DOMAIN(vdDerivedObject, value); derived_object_genus_t genus = get_derived_object_genus(value); genus_descriptor_t *descriptor = get_genus_descriptor(genus); (descriptor->print_on)(value, context); }
static void custom_tagged_print_on(value_t value, print_on_context_t *context) { CHECK_DOMAIN(vdCustomTagged, value); phylum_behavior_t *behavior = get_custom_tagged_behavior(value); (behavior->print_on)(value, context); }
static void heap_object_print_on(value_t value, print_on_context_t *context) { CHECK_DOMAIN(vdHeapObject, value); family_behavior_t *behavior = get_heap_object_family_behavior(value); (behavior->print_on)(value, context); }
static void condition_print_on(value_t value, string_buffer_t *buf) { CHECK_DOMAIN(vdCondition, value); condition_cause_t cause = get_condition_cause(value); const char *cause_name = get_condition_cause_name(cause); string_buffer_printf(buf, "%%<condition: %s(", cause_name); uint32_t details = get_condition_details(value); switch (cause) { case ccInvalidSyntax: { invalid_syntax_cause_t cause = (invalid_syntax_cause_t) details; string_buffer_printf(buf, "%s", get_invalid_syntax_cause_name(cause)); break; } case ccUnsupportedBehavior: { unsupported_behavior_details_codec_t codec; codec.encoded = details; unsupported_behavior_cause_t cause = (unsupported_behavior_cause_t) codec.decoded.cause; string_buffer_printf(buf, "%s", get_unsupported_behavior_cause_name(cause)); value_type_info_t type = value_type_info_decode(codec.decoded.type_info); string_buffer_printf(buf, " of %s", value_type_info_name(type)); break; } case ccLookupError: { lookup_error_cause_t cause = (lookup_error_cause_t) details; string_buffer_printf(buf, "%s", get_lookup_error_cause_name(cause)); break; } case ccSystemError: { system_error_cause_t cause = (system_error_cause_t) details; string_buffer_printf(buf, "%s", get_system_error_cause_name(cause)); break; } case ccInvalidInput: { if (details != 0) { // If no hint is given (or the hint it the empty string) the details // field will be 0. invalid_input_details_codec_t codec; codec.encoded = details; char hint[7]; string_hint_to_c_str(codec.decoded, hint); string_buffer_printf(buf, "%s", hint); } break; } case ccNotSerializable: { value_type_info_t type = value_type_info_decode((uint16_t) details); string_buffer_printf(buf, "%s", value_type_info_name(type)); break; } case ccUnexpectedType: { unexpected_type_info_codec_t codec; codec.encoded = details; value_type_info_t expected = value_type_info_decode(codec.decoded.expected); if (!value_type_info_is_empty(expected)) // It's okay to leave out the expected type, we skip printing it if it's // not there. string_buffer_printf(buf, "expected: %s, ", value_type_info_name(expected)); value_type_info_t found = value_type_info_decode(codec.decoded.found); string_buffer_printf(buf, "found: %s", value_type_info_name(found)); break; } case ccUncaughtSignal: { string_buffer_printf(buf, is_uncaught_signal_escape(value) ? "escape" : "non-escape"); break; } default: { string_buffer_printf(buf, "dt@%i", details); break; } } string_buffer_printf(buf, ")>"); }
static void integer_print_on(value_t value, print_on_context_t *context) { CHECK_DOMAIN(vdInteger, value); const char *fmt = (context->flags & pfHex) ? "%llx" : "%lli"; string_buffer_printf(context->buf, fmt, get_integer_value(value)); }