示例#1
0
$x->post_dec_prop(N);
$t = end_test($t, '$this->x--', $overhead);
$x->isset_prop(N);
$t = end_test($t, 'isset($this->x)', $overhead);
$x->empty_prop(N);
$t = end_test($t, 'empty($this->x)', $overhead);
$x->call(N);
$t = end_test($t, '$this->f()', $overhead);
$x->read_const(N);
$t = end_test($t, '$x = Foo::TEST', $overhead);
create_object(N);
$t = end_test($t, 'new Foo()', $overhead);
read_const(N);
$t = end_test($t, '$x = TEST', $overhead);
read_auto_global(N);
$t = end_test($t, '$x = $_GET', $overhead);
read_global_var(N);
$t = end_test($t, '$x = $GLOBALS[\'v\']', $overhead);
read_hash(N);
$t = end_test($t, '$x = $hash[\'v\']', $overhead);
read_str_offset(N);
$t = end_test($t, '$x = $str[0]', $overhead);
issetor(N);
$t = end_test($t, '$x = $a ?: null', $overhead);
issetor2(N);
$t = end_test($t, '$x = $f ?: tmp', $overhead);
ternary(N);
$t = end_test($t, '$x = $f ? $f : $a', $overhead);
ternary2(N);
$t = end_test($t, '$x = $f ? $f : tmp', $overhead);
total($t0, "Total");
示例#2
0
function read_hash($fh, $hash_entry_ptr, $index_list)
{
    if (gettype($index_list) != 'array') {
        throw new Exception('array expected');
    }
    $ptr = $hash_entry_ptr;
    if (TRACE) {
        printf("============\nread_hash: \$ptr: 0x%X\n", $ptr);
    }
    if (!$ptr) {
        return array();
    }
    $index = array_shift($index_list);
    if (!is_null($index)) {
        $single_search = count($index_list) ? SINGLE_SEARCH_FOR_SUBHASH : SINGLE_SEARCH_FOR_SCALAR;
    }
    $is_first_round = 1;
    $prev_rec_ptr = $ptr;
    $result = array();
    # обход записей хэша
    while ($ptr = $prev_rec_ptr) {
        if (TRACE) {
            printf("read record: \$ptr 0x%X\n", $ptr);
        }
        if (TRACE) {
            printf("\$is_first_round: %d, \$single_search: %d, \$index: %d \n", $is_first_round, $single_search, $index);
        }
        # чтение rec_desc
        $rec_desc = read_rec_desc($fh, $ptr);
        $field_qt = $rec_desc['FIELD_QT_BITS'];
        $ref_size = $rec_desc['REF_SIZE_BITS'];
        # если первая запись и текущая запись является узловой
        if ($is_first_round && $rec_desc['FIELD_QT_BITS'] == 0) {
            $list_entry_pos = ftell($fh);
            if (TRACE) {
                printf("\$list_entry_pos: 0x%X, \$single_search: %d, \$index: %d\n", $list_entry_pos, $single_search, $index);
            }
            if ($single_search && $index > 0) {
                $list_item_addr = force_get_list_item_addr($fh, $list_entry_pos, $index, false);
                if (is_null($list_item_addr)) {
                    return NULL;
                }
                if (TRACE) {
                    printf("\$list_item_addr: 0x%X\n", $list_item_addr);
                }
                $list_item_hash_entry_ptr = read_hash_entry($fh, $list_item_addr);
                return read_hash($fh, $list_item_hash_entry_ptr, $index_list);
            } elseif (!$single_search) {
                $pos = $list_entry_pos;
                $index_base = 0;
                $ptrs = NULL;
                $i = NULL;
                $stack = array();
                array_push($stack, array());
                $level = 0;
                if (TRACE) {
                    printf("\$pos: 0x%X\n", $pos);
                }
                while (count($stack)) {
                    if (is_null($ptrs)) {
                        if (TRACE) {
                            printf("read list section[0x%X]\n", $pos);
                        }
                        # считываем элементы секции списка
                        $array = unpack('N256', read_buf(1024, $fh, SEEK_SET, $pos));
                        $ptrs = array_values($array);
                        $i = count($stack) == 1 ? 1 : 0;
                    } else {
                        $i++;
                    }
                    # if (TRACE) printf("check list item[0x%X]: ptrs[%d]=0x%X, level=$level, count(\$stack)=%s\n", $pos, $i, $ptrs[$i], $level, count($stack));
                    if ($i > 0xff) {
                        array_pop($stack);
                        if (count($stack)) {
                            $top = $stack[count($stack) - 1];
                            $pos = $top['pos'];
                            $index_base = $top['index_base'];
                            $ptrs = $top['ptrs'];
                            $i = $top['i'];
                        } elseif ($ptrs[0] && $level < 3) {
                            # && $level < 3 -- предохранитель
                            $pos = $ptrs[0];
                            $index_base = 0;
                            $ptrs = NULL;
                            $i = NULL;
                            array_push($stack, array());
                            $level += 1;
                        }
                    } elseif ($ptrs[$i]) {
                        if ($level - count($stack) + 1 == 0) {
                            $result[$index_base + $i] = read_hash($fh, $ptrs[$i], $index_list);
                        } else {
                            # переход к "нижней" секции
                            $top =& $stack[count($stack) - 1];
                            $top['pos'] = $pos;
                            $top['index_base'] = $index_base;
                            $top['ptrs'] = $ptrs;
                            $top['i'] = $i;
                            $pos = $ptrs[$i];
                            $index_base = $index_base + $i << 8;
                            $ptrs = NULL;
                            $i = NULL;
                            array_push($stack, array());
                        }
                    }
                }
            }
            $is_first_round = 0;
            $prev_rec_ptr = read_int(4, $fh, SEEK_SET, $list_entry_pos + 1024);
            if (TRACE) {
                printf("\$prev_rec_ptr: 0x%X\n", $prev_rec_ptr);
            }
        } elseif (!$is_first_round && !$field_qt) {
            $ref = !$ref_size ? 0 : read_int($ref_size, $fh, SEEK_CUR, 1024 + 4);
            $prev_rec_ptr = !$ref ? 0 : $ptr - $ref;
            if (TRACE) {
                printf("\$prev_rec_ptr: 0x%X\n", $prev_rec_ptr);
            }
        } else {
            if ($is_first_round) {
                if ($single_search && $index > 0) {
                    return NULL;
                }
                $is_first_round = 0;
            }
            if ($field_qt == FIELD_QT_READ_MASK) {
                $field_qt = read_int(1, $fh, SEEK_CUR, 0) + 1;
            }
            $field_defs_len = $field_qt * 2;
            if (TRACE) {
                printf("\$field_defs_len: %d\n", $field_defs_len);
            }
            if (DUMP) {
                $dump_field_def_pos = ftell($fh) - 1;
            }
            # чтение FIELD_DEFS и REF
            $buf = read_buf($field_defs_len + $ref_size, $fh, SEEK_CUR, 0);
            $field_defs = unpack("C{$field_defs_len}", $buf);
            $fields = array();
            $hash_ids = array();
            $SSS_sum = 0;
            for ($i = 1; $i <= $field_defs_len; $i += 2) {
                $id = -$field_defs[$i];
                $def =& $field_defs[$i + 1];
                $type = $def & STRINT_TYPE_MASK;
                if (!$type) {
                    $type = $def;
                }
                $SSS = ($def & SSS_READ_MASK) >> SSS_SHIFT;
                $SSS_sum += $SSS;
                $field = array('type' => $type, 'SSS' => $SSS, 'idx' => ($i - 1) / 2);
                if ($type == STRING_TYPE) {
                    $field['RRR'] = ($def & RRR_READ_MASK) >> RRR_SHIFT;
                }
                $fields[$id] = $field;
                $hash_ids[] = $id;
                if ($id == $index && $single_search) {
                    $index_field_type = $fields[$index]['type'];
                    if ($single_search == SINGLE_SEARCH_FOR_SUBHASH && $index_field_type != HASH_TYPE || $index_field_type == NULL_TYPE) {
                        return NULL;
                    }
                } elseif ($type == NULL_TYPE && !$single_search && !array_key_exists($id, $result)) {
                    $result[$id] = NULL;
                }
            }
            # парсинг REF
            $ref = $ref_size ? unpack_int($ref_size, substr($buf, -$ref_size, $ref_size)) : 0;
            $prev_rec_ptr = $ref ? $ptr - $ref : 0;
            $skip_len = 0;
            $back_len = 0;
            $short_values_buf = read_buf($SSS_sum, $fh, SEEK_CUR, 0);
            if (TRACE) {
                printf("\$SSS_sum: %d, strlen(\$short_values_buf): %d\n", $SSS_sum, strlen($short_values_buf));
            }
            # обход ключей хэша
            $sids = array();
            $hids = array();
            foreach ($hash_ids as $id) {
                $field =& $fields[$id];
                $type =& $field['type'];
                $SSS =& $field['SSS'];
                $dont_skip_this_field = $single_search && ($index == $id || $index < $id && $index_field_type == STRING_TYPE && $type == STRING_TYPE) || !$single_search && ($type == STRING_TYPE || !array_key_exists($id, $result));
                if (TRACE) {
                    printf("\$id: %d, \$type: %d, \$SSS: %d, \$dont_skip_this_field: %d\n", $id, $type, $SSS, $dont_skip_this_field);
                }
                if (!$dont_skip_this_field) {
                    $skip_len += $SSS;
                    if (TRACE) {
                        printf("\$id: %d, \$skip_len: %d\n", $id, $skip_len);
                    }
                } else {
                    if (TRACE) {
                        printf("\$skip_len: %d, \$SSS: %d, strlen(substr(\$short_values_buf, \$skip_len, \$SSS)): %d\n", $skip_len, $SSS, strlen(substr($short_values_buf, $skip_len, $SSS)));
                    }
                    $short_value = unpack_int($SSS, substr($short_values_buf, $back_len + $skip_len, $SSS));
                    $back_len += $skip_len + $SSS;
                    $skip_len = 0;
                    if (TRACE) {
                        printf("\$short_value: 0x%X\n", $short_value);
                    }
                    if ($type == INTEGER_TYPE) {
                        if ($single_search) {
                            return $short_value;
                        }
                        $field['value'] = $short_value;
                    } elseif ($type == STRING_TYPE) {
                        $field['short_value'] = $short_value;
                        $sids[] = $id;
                    } elseif ($type == HASH_TYPE) {
                        if (TRACE) {
                            printf("\$field['value_hash_entry_ptr']: 0x%X\n", $short_value);
                        }
                        $field['value_hash_entry_ptr'] = $short_value;
                        $hids[] = $id;
                    } else {
                        throw new Exception("unexpected type {$type}");
                    }
                    if ($single_search && $index == $id) {
                        break;
                    }
                }
            }
            # обход коротких значений
            $skip_len = 0;
            if ($sids) {
                foreach ($sids as $id) {
                    $field =& $fields[$id];
                    $short_value =& $field['short_value'];
                    if (TRACE) {
                        printf("sids: \$id: %d; \$short_value: %d\n", $id, $short_value);
                    }
                    if ($single_search && $index == $id || !$single_search && !array_key_exists($id, $result)) {
                        if (TRACE) {
                            printf("sids: \$short_value: %d, \$skip_len: %d\n", $short_value, $skip_len);
                        }
                        $value = read_buf($short_value, $fh, SEEK_CUR, $skip_len);
                        $skip_len = 0;
                        $RRR =& $field['RRR'];
                        if ($RRR) {
                            $RRR_buf = substr($value, -$RRR, $RRR);
                            $tail_len = unpack_int(strlen($RRR_buf), $RRR_buf);
                            if ($tail_len) {
                                $value = substr($value, 0, -$tail_len);
                            }
                        }
                        if ($single_search) {
                            return $value;
                        }
                        $field['value'] = $value;
                    } else {
                        $skip_len += $short_value;
                        if (TRACE) {
                            printf("sids: \$skip_len: %d\n", $skip_len);
                        }
                    }
                }
            }
            if ($hids) {
                foreach ($hids as $id) {
                    $field =& $fields[$id];
                    $field['value'] = read_hash($fh, $field['value_hash_entry_ptr'], $index_list);
                    if ($single_search) {
                        return $field['value'];
                    }
                }
            }
            foreach ($hash_ids as $id) {
                if (!array_key_exists($id, $result)) {
                    $result[$id] = $fields[$id]['value'];
                }
            }
        }
    }
    return $single_search ? NULL : $result;
}