éåžžãstrlenã¡ãœããã䜿çšãããŸãã
if (strlen($name) > 49) { ... }
ãã ãããã®ãªãã·ã§ã³ã¯ãããããçŽ20ïŒ é ããªããŸãã
if (isset($name[49])) { ... }
ããããã ã ãœãŒã¹ãéããŠããã¹ãŠã®strlenïŒïŒåŒã³åºããissetïŒïŒã«çœ®ãæããããšããŠããŸãã ãããã å ã®èšäºã泚ææ·±ãèªãã å Žåãããã©ãŒãã³ã¹ã20ïŒ ç°ãªãçç±ã¯ã strlenïŒïŒã®è€æ°åã®åŒã³åºãã§ã 60ã80,000åã®ç¹°ãè¿ãã§ããããšãããããŸãã
ãªãã§ïŒ
strlenïŒïŒãPHPã®æååã®é·ããã©ã®ããã«èšç®ãããã¯åé¡ã§ã¯ãããŸããããããã®æååã¯ãã¹ãŠããã®ã¡ãœãããåŒã³åºãããæç¹ã§ãã§ã«ããã£ãŠããããã§ãã å¯èœãªéããã»ãšãã©ã¯ã³ã³ãã€ã«æã«èšç®ãããŸãã ã¡ã¢ãªã«éä¿¡ãããPHPæååã®é·ãã¯ããã®æååãå«ãCæ§é äœã«ã«ãã»ã«åãããŸãã ãããã£ãŠã strlenïŒïŒã¯åã«ãã®æ å ±ãèªã¿åãããã®ãŸãŸè¿ããŸãã ããã¯ãããããäœãèšç®ããªããããPHPé¢æ°ã®äžã§æãé«éã§ãã ãœãŒã¹ã³ãŒãã¯æ¬¡ã®ãšããã§ãã
ZEND_FUNCTION(strlen) { char *s1; int s1_len; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &s1, &s1_len) == FAILURE) { return; } RETVAL_LONG(s1_len); }
issetïŒïŒãé¢æ°ã§ã¯ãªãããšãèãããšã strlenïŒïŒã®ããã©ãŒãã³ã¹ã20ïŒ äœäžããçç±ã¯ãäž»ã«Zendãšã³ãžã³ã§é¢æ°ãåŒã³åºãéã®é¢é£ããé 延ã«ãããã®ã§ãã
å¥ã®ãã€ã³ãããããŸãïŒ strlenïŒïŒã®ããã©ãŒãã³ã¹ãä»ã®ãã®ãšæ¯èŒãããšããè¿œå ã®ãªãã³ãŒããè¿œå ãããŸãã ãŸãã issetïŒïŒã®å Žåã䜿çšãããäžæã®ãªãã³ãŒãã¯1ã€ã ãã§ãã
éã¢ã»ã³ãã«ãããifïŒstrlenïŒïŒïŒæ§é ã®äŸïŒ
line #* IO op fetch ext return operands ----------------------------------------------------------------------------------- 3 0 > SEND_VAR !0 1 DO_FCALL 1 $0 'strlen' 2 IS_SMALLER ~1 42, $0 3 > JMPZ ~1, ->5 5 4 > > JMP ->5 6 5 > > RETURN 1
ãããŠãããã¯ifïŒissetïŒïŒïŒã®æå³çã«ç䟡ãªæ§é ã§ãïŒ
line #* IO op fetch ext return operands ----------------------------------------------------------------------------------- 3 0 > ISSET_ISEMPTY_DIM_OBJ 33554432 ~0 !0, 42 1 > JMPZ ~0, ->3 5 2 > > JMP ->3 6 3 > > RETURN 1
ã芧ã®ãšããã issetïŒïŒã³ãŒãã«ã¯é¢æ°ïŒDO_FCALLïŒã®åŒã³åºãã¯å«ãŸããŠããŸããã ãŸãããªãã³ãŒãIS_SMALLERã¯ãããŸããïŒRETURNã¹ããŒãã¡ã³ãã¯ç¡èŠããŠãã ããïŒã issetïŒïŒã¯ããŒã«å€ãçŽæ¥è¿ããŸãã strlenïŒïŒã¯æåã«äžæå€æ°ãè¿ãã次ã«ããããªãã³ãŒãIS_SMALLERã«æž¡ãããæçµçµæã¯ifïŒïŒã䜿çšããŠèšç®ãããŸãã ã€ãŸãã2ã€ã®ãªãã³ãŒããstrlenïŒïŒæ§é ã§äœ¿çšããã1ã€ãissetïŒïŒæ§é ã§äœ¿çšãããŸãã ãããã£ãŠãéåžžã¯1ã€ã®æäœã2ã€ãããéãããã issetïŒïŒã®æ¹ãããã©ãŒãã³ã¹ãé«ããªããŸãã
PHPã§ã®é¢æ°åŒã³åºãã®ä»çµã¿ãšissetïŒïŒãšã®éããèŠãŠã¿ãŸãããã
PHPé¢æ°åŒã³åºã
æãé£ããéšåã¯ãé¢æ°åŒã³åºãã«é¢é£ä»ããããŠããä»®æ³ãã·ã³ã®éšåïŒPHPã³ãŒããå®è¡ãããç¬éïŒãåæããããšã§ãã é¢æ°åŒã³åºãã«é¢é£ããç¬éãæãäžããããšãªããæ¬è³ªãè¿°ã¹ãããšããŸãã
å§ããããã«ãåŒã³åºãã®å®è¡æéãåæããŸãããã ã³ã³ãã€ã«æã« ãPHPé¢æ°ã«é¢é£ããæäœãå®è¡ããã«ã¯å€ãã®ãªãœãŒã¹ãå¿ èŠã§ãã ãã ãããªãã³ãŒããã£ãã·ã¥ã䜿çšããã°ãã³ã³ãã€ã«äžã«åé¡ã¯çºçããŸããã
ç¹å®ã®ã¹ã¯ãªãããã³ã³ãã€ã«ãããšããŸãã å®è¡æã«äœãèµ·ãããã ããåæããŸãããã ããã¯ãå éšé¢æ°ïŒãã®å Žåã¯strlenïŒïŒ ïŒã®åŒã³åºãã®ãªãã³ãŒãã®ãã³ããã©ã®ããã«èŠãããã§ãïŒ
strlen($a); line #* IO op fetch ext return operands ----------------------------------------------------------------------------------- 3 0 > SEND_VAR !0 1 DO_FCALL 1 'strlen'
é¢æ°åŒã³åºãã®ã¡ã«ããºã ãç解ããã«ã¯ã次ã®2ã€ã®ããšãç¥ãå¿ èŠããããŸãã
- é¢æ°åŒã³åºããšã¡ãœããåŒã³åºãã¯åããã®ã§ã
- ãŠãŒã¶ãŒé¢æ°åŒã³åºããšå éšé¢æ°åŒã³åºãã¯ç°ãªãæ¹æ³ã§åŠçãããŸã
ããããæåŸã®äŸããå éšãé¢æ°ã®åŒã³åºãã«ã€ããŠèª¬æããŠããçç±ã§ããstrlenïŒïŒã¯ãCã³ãŒãã®äžéšã§ããPHPé¢æ°ã§ãã ããŠãŒã¶ãŒå®çŸ©ãPHPé¢æ°ïŒã€ãŸããPHPèšèªã§èšè¿°ãããé¢æ°ïŒã®ãªãã³ãŒãããã³ãããå ŽåããŸã£ããåããªãã³ãŒããŸãã¯ä»ã®ãªãã³ãŒããååŸã§ããŸãã
å®éããã®é¢æ°ãPHPã§èªèãããŠãããã©ããã«é¢ä¿ãªããã³ã³ãã€ã«æã«åããªãã³ãŒããçæããŸããã æããã«ãå éšPHPé¢æ°ã¯ã³ã³ãã€ã©ãŒãéå§ããåã«å®£èšããããããã³ã³ãã€ã«æã«ç¥ãããŠããŸãã ãã ããã«ã¹ã¿ã é¢æ°ã¯ã宣èšãããåã«åŒã³åºãããå¯èœæ§ããããããæ確ã§ãªãå ŽåããããŸãã å®è¡ã«ã€ããŠèª¬æããå Žåãå éšPHPé¢æ°ã¯ã«ã¹ã¿ã é¢æ°ãããå¹ççã§ããããã«ãå©çšå¯èœãªæ€èšŒã¡ã«ããºã ãå€ããããŸãã
äžèšã®äŸãããé¢æ°åŒã³åºããå¶åŸ¡ããããã«è€æ°ã®ãªãã³ãŒãã䜿çšãããŠããããšãããããŸãã ãŸããé¢æ°ã«ã¯ç¬èªã®ã¹ã¿ãã¯ãããããšãèŠããŠããå¿ èŠããããŸãã PHPã§ã¯ãä»ã®èšèªãšåæ§ã«ãé¢æ°ãåŒã³åºãã«ã¯ãæåã«ã¹ã¿ãã¯ãã¬ãŒã ãäœæããé¢æ°ã«åŒæ°ãæž¡ãå¿ èŠããããŸãã 次ã«ããããã®åŒæ°ãå¿ èŠã«å¿ããŠã¹ã¿ãã¯ãããã«ããé¢æ°ãåŒã³åºããŸãã åŒã³åºãã®çµããã«ã以åã«äœæããããã¬ãŒã ãç Žæ£ããå¿ èŠããããŸãã
ããã¯ãé¢æ°åŒã³åºããæ±ãã¹ããŒã ãäžè¬çãªåœ¢ã§ã©ã®ããã«èŠãããã§ãã ãã ããPHPã¯ãã¹ã¿ãã¯ãã¬ãŒã ãäœæããã³åé€ããæé ã®æé©åãæäŸããŸãã ããã«ããã¹ãŠã®é¢æ°åŒã³åºãã§ãããã®ãžã§ã¹ãã£ããã¹ãŠå®è¡ããå¿ èŠããªãããã«ãå®è¡ã延æã§ããŸãã
ãªãã³ãŒãSEND_VARã¯ãã¹ã¿ãã¯ãã¬ãŒã ã«åŒæ°ãéä¿¡ããŸãã ã³ã³ãã€ã©ãŒã¯ãé¢æ°ãåŒã³åºãåã«å¿ ããã®ãããªãªãã³ãŒããçæããŸãã ããã«ãå€æ°ããšã«ç¬èªã®å€æ°ãäœæãããŸãã
$a = '/'; setcookie('foo', 'bar', 128, $a); line #* IO op fetch ext return operands ----------------------------------------------------------------------------------- 3 0 > ASSIGN !0, '%2F' 4 1 SEND_VAL 'foo' 2 SEND_VAL 'bar' 3 SEND_VAL 128 4 SEND_VAR !0 5 DO_FCALL 4 'setcookie'
ããã«å¥ã®ãªãã³ãŒã-SEND_VALããããŸãã åèšã§ãé¢æ°ã¹ã¿ãã¯ã«äœããéä¿¡ããããã®4çš®é¡ã®ãªãã³ãŒãããããŸãã
- SEND_VAL ïŒ å®æ°å€ ïŒæååãæŽæ°ãªã©ïŒãéä¿¡ããŸã
- SEND_VAR ïŒPHPå€æ°ïŒ$ aïŒãéä¿¡ããŸã
- SEND_REF ïŒPHPå€æ°ãããªã³ã¯ã§åŒæ°ãåãé¢æ°ãžã®ãªã³ã¯ãšããŠéä¿¡ããŸã
- SEND_VAR_NO_REF ïŒãã¹ããããé¢æ°ã®å Žåã«äœ¿çšãããæé©åããããã³ãã©ãŒ
SEND_VARã¯äœãããŸããïŒ
ZEND_VM_HELPER(zend_send_by_var_helper, VAR|CV, ANY) { USE_OPLINE zval *varptr; zend_free_op free_op1; varptr = GET_OP1_ZVAL_PTR(BP_VAR_R); if (varptr == &EG(uninitialized_zval)) { ALLOC_ZVAL(varptr); INIT_ZVAL(*varptr); Z_SET_REFCOUNT_P(varptr, 0); } else if (PZVAL_IS_REF(varptr)) { zval *original_var = varptr; ALLOC_ZVAL(varptr); ZVAL_COPY_VALUE(varptr, original_var); Z_UNSET_ISREF_P(varptr); Z_SET_REFCOUNT_P(varptr, 0); zval_copy_ctor(varptr); } Z_ADDREF_P(varptr); zend_vm_stack_push(varptr TSRMLS_CC); FREE_OP1(); /* for string offsets */ CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); }
SEND_VARã¯ãå€æ°ãåç §ãã©ããã確èªããŸãã ãã®å Žåãããã¯ãããåé¢ããããã«ãã£ãŠãªã³ã¯ã®äžäžèŽãäœæããŸãã ãããéåžžã«æªãçç±ã¯ãç§ã®å¥ã®èšäºã§èªãããšãã§ããŸãã 次ã«ãSEND_VARãå€æ°ãžã®ãªã³ã¯ã®æ°ïŒããã§ã®ãªã³ã¯ã¯PHPã®èŠ³ç¹ããã®ãªã³ã¯ã§ã¯ãªããã€ãŸãïŒã§ã¯ãªãããã®å€ã䜿çšããæ°ã®åãªãã€ã³ãžã±ãŒã¿ãŒïŒãå€æ°ã«è¿œå ããä»®æ³ãã·ã³ã¹ã¿ãã¯ã«éä¿¡ããŸãã
Z_ADDREF_P(varptr); zend_vm_stack_push(varptr TSRMLS_CC);
é¢æ°ãåŒã³åºããã³ã«ãã¹ã¿ãã¯ãžã®åå€æ°åŒæ°ã®åç §ã«ãŠã³ãã1ãã€å¢ãããŸãã ããã¯ãå€æ°ãé¢æ°ã³ãŒãã§ã¯ãªãã¹ã¿ãã¯ã«ãã£ãŠåç §ãããããã§ãã å€æ°ãã¹ã¿ãã¯ã«éä¿¡ããŠãããã©ãŒãã³ã¹ã«ã¯ã»ãšãã©åœ±é¿ããŸããããã¹ã¿ãã¯ã¯ã¡ã¢ãªãæ¶è²»ããŸãã å®è¡æã«ãã®äžã«é 眮ãããŸããããµã€ãºã¯ã³ã³ãã€ã«æã«èšç®ãããŸãã å€æ°ãã¹ã¿ãã¯ã«éä¿¡ããåŸãDO_FCALLãå®è¡ããŸãã 以äžã¯ãPHPé¢æ°ã®åŒã³åºãããé ãã¹ããŒãã¡ã³ãããšèŠãªãããã«äœ¿çšãããã³ãŒããšãã§ãã¯ã®éã®äŸã§ãã
ZEND_VM_HANDLER(60, ZEND_DO_FCALL, CONST, ANY) { USE_OPLINE zend_free_op free_op1; zval *fname = GET_OP1_ZVAL_PTR(BP_VAR_R); call_slot *call = EX(call_slots) + opline->op2.num; if (CACHED_PTR(opline->op1.literal->cache_slot)) { EX(function_state).function = CACHED_PTR(opline->op1.literal->cache_slot); } else if (UNEXPECTED(zend_hash_quick_find(EG(function_table), Z_STRVAL_P(fname), Z_STRLEN_P(fname)+1, Z_HASH_P(fname), (void **) &EX(function_state).function)==FAILURE)) { SAVE_OPLINE(); zend_error_noreturn(E_ERROR, "Call to undefined function %s()", fname->value.str.val); } else { CACHE_PTR(opline->op1.literal->cache_slot, EX(function_state).function); } call->fbc = EX(function_state).function; call->object = NULL; call->called_scope = NULL; call->is_ctor_call = 0; EX(call) = call; FREE_OP1(); ZEND_VM_DISPATCH_TO_HELPER(zend_do_fcall_common_helper); }
ã芧ã®ãšãããããã§å°ããªãã§ãã¯ãè¡ãããããŸããŸãªãã£ãã·ã¥ã䜿çšãããŸããã ããšãã°ããã³ãã©ãŒãã€ã³ã¿ãŒãæåã®åŒã³åºããæ€åºãããã®åŸã®ååŒã³åºãããã®ãã€ã³ã¿ãŒã䜿çšã§ããããã«ãä»®æ³ãã·ã³ã®ã¡ã€ã³ãã¬ãŒã ã«ãã£ãã·ã¥ãããŸããã
次ã«ã zend_do_fcall_common_helperïŒïŒãåŒã³åºããŸãã ãã®é¢æ°ã®ã³ãŒãã¯ããã«æçš¿ããŸããããããªã¥ãŒã ã倧ããããŸãã ããã§å®è¡ãããæäœã®ã¿ã衚瀺ããŸãã èŠããã«ããããã¯å®è¡äžã«è¡ãããããŸããŸãªãã§ãã¯ã§ãã PHPã¯åçèšèªã§ãããå®è¡æã«æ°ããé¢æ°ãšã¯ã©ã¹ã宣èšããåæã«ãã¡ã€ã«ãèªåçã«ã¢ããããŒãã§ããŸãã ãã®ãããPHPã¯å®è¡æã«å€ãã®ãã§ãã¯ãå®è¡ããããåŸããããã©ãŒãã³ã¹ã«æªåœ±é¿ãåãŒããŸãã ãããããããåé¿ããããšã¯ã§ããŸããã
if (UNEXPECTED((fbc->common.fn_flags & (ZEND_ACC_ABSTRACT|ZEND_ACC_DEPRECATED)) != 0)) { if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_ABSTRACT) != 0)) { zend_error_noreturn(E_ERROR, "Cannot call abstract method %s::%s()", fbc->common.scope->name, fbc->common.function_name); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); /* Never reached */ } if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_DEPRECATED) != 0)) { zend_error(E_DEPRECATED, "Function %s%s%s() is deprecated", fbc->common.scope ? fbc->common.scope->name : "", fbc->common.scope ? "::" : "", fbc->common.function_name); } } if (fbc->common.scope && !(fbc->common.fn_flags & ZEND_ACC_STATIC) && !EX(object)) { if (fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) { /* FIXME: output identifiers properly */ zend_error(E_STRICT, "Non-static method %s::%s() should not be called statically", fbc->common.scope->name, fbc->common.function_name); } else { /* FIXME: output identifiers properly */ /* An internal function assumes $this is present and won't check that. So PHP would crash by allowing the call. */ zend_error_noreturn(E_ERROR, "Non-static method %s::%s() cannot be called statically", fbc->common.scope->name, fbc->common.function_name); } }
å°åæã®æ°ãã芧ãã ããã ã©ãã
if (fbc->type == ZEND_USER_FUNCTION || fbc->common.scope) { should_change_scope = 1; EX(current_this) = EG(This); EX(current_scope) = EG(scope); EX(current_called_scope) = EG(called_scope); EG(This) = EX(object); EG(scope) = (fbc->type == ZEND_USER_FUNCTION || !EX(object)) ? fbc->common.scope : NULL; EG(called_scope) = EX(call)->called_scope; }
é¢æ°ã®åæ¬äœã«ã¯ãå€æ°ã«å¯Ÿããç¬èªã®ã¹ã³ãŒããããããšãããã£ãŠããŸãã ãšã³ãžã³ã¯ãæ©èœã³ãŒããåŒã³åºãåã«å¯èŠæ§ããŒãã«ãåãæ¿ããŸãããã®ãããå€æ°ãèŠæ±ãããšã察å¿ããããŒãã«ã§æ€åºãããŸãã ãŸããé¢æ°ãšã¡ãœããã¯æ¬è³ªçã«åããã®ã§ããããã $ thisãã€ã³ã¿ãŒãã¡ãœããã«ãã€ã³ãããæ¹æ³ã«ã€ããŠèªãããšãã§ããŸãã
if (fbc->type == ZEND_INTERNAL_FUNCTION) {
äžã§è¿°ã¹ãããã«ãå éšé¢æ°ïŒCã®äžéšïŒã«ã¯ç°ãªãå®è¡ãã¹ãããããŠãŒã¶ãŒå®çŸ©é¢æ°ãšã¯ç°ãªããŸãã éåžžããŠãŒã¶ãŒå®çŸ©ã®æ©èœãšã¯èšããªãå éšæ©èœã«ã€ããŠãšã³ãžã³ã«éç¥ã§ãããããããçãæé©åãããŠããŸãã
fbc->internal_function.handler(opline->extended_value, ret->var.ptr, (fbc->common.fn_flags & ZEND_ACC_RETURN_REFERENCE) ? &ret->var.ptr : NULL, EX(object), RETURN_VALUE_USED(opline) TSRMLS_CC);
äžèšã®è¡ã¯ãå éšé¢æ°ãã³ãã©ãŒãåŒã³åºããŸãã strlenïŒïŒã«é¢ããäŸã®å Žåããã®è¡ã¯ã³ãŒããåŒã³åºããŸãã
/* PHP's strlen() source code */ ZEND_FUNCTION(strlen) { char *s1; int s1_len; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &s1, &s1_len) == FAILURE) { return; } RETVAL_LONG(s1_len); }
strlenïŒïŒã¯äœãããŸããïŒ zend_parse_parametersïŒïŒã䜿çšããŠãã¹ã¿ãã¯ããåŒæ°ãååŸããŸãã ããã¯ãé ããé¢æ°ã§ããã¹ã¿ãã¯ãäžããåŒæ°ãé¢æ°ãæåŸ ããåïŒãã®å Žåã¯æååïŒã«å€æããå¿ èŠãããããã§ãã ãããã£ãŠã strlenïŒïŒã®ã¹ã¿ãã¯ã«äœãæž¡ããŠããåŒæ°ã®å€æãå¿ èŠã«ãªãå Žåããããããã¯ããã©ãŒãã³ã¹ã®é¢ã§æãç°¡åãªããã»ã¹ã§ã¯ãããŸããã ãœãŒã¹ã³ãŒãzend_parse_parametersïŒïŒã¯ãé¢æ°ã®ã¹ã¿ãã¯ãã¬ãŒã ããåŒæ°ãååŸããéã«ããã»ããµãå®è¡ããªããã°ãªããªãæäœã®æ°ã®è¯ãã¢ã€ãã¢ãæäŸããŸãã
次ã®ã¹ãããã«é²ã¿ãŸãã é¢æ°ã®æ¬äœã³ãŒããå®è¡ããã ãã§ãä»åºŠã¯ãæŽçãããå¿ èŠããããŸãã ã¹ã³ãŒãã埩å ããããšããå§ããŸãããïŒ
if (should_change_scope) { if (EG(This)) { if (UNEXPECTED(EG(exception) != NULL) && EX(call)->is_ctor_call) { if (EX(call)->is_ctor_result_used) { Z_DELREF_P(EG(This)); } if (Z_REFCOUNT_P(EG(This)) == 1) { zend_object_store_ctor_failed(EG(This) TSRMLS_CC); } } zval_ptr_dtor(&EG(This)); } EG(This) = EX(current_this); EG(scope) = EX(current_scope); EG(called_scope) = EX(current_called_scope); }
次ã«ãã¹ã¿ãã¯ãã¯ãªã¢ããŸãã
zend_vm_stack_clear_multiple(1 TSRMLS_CC);
æåŸã«ãé¢æ°ã®å®è¡äžã«ããã€ãã®äŸå€ãçºçããå Žåãä»®æ³ãã·ã³ããã®äŸå€ã®catchãããã¯ã«èªå°ããå¿ èŠããããŸãã
if (UNEXPECTED(EG(exception) != NULL)) { zend_throw_exception_internal(NULL TSRMLS_CC); if (RETURN_VALUE_USED(opline) && EX_T(opline->result.var).var.ptr) { zval_ptr_dtor(&EX_T(opline->result.var).var.ptr); } HANDLE_EXCEPTION(); }
PHPé¢æ°åŒã³åºãã«ã€ããŠ
ããã§ãã³ã³ãã¥ãŒã¿ãŒããéåžžã«å°ããåçŽãªã strlenïŒïŒé¢æ°ã®åŒã³åºãã«è²»ããæéãæ³åã§ããŸãã ãŸããè€æ°ååŒã³åºãããããããã®æéããããšãã°25,000åã«å¢ãããŸãã ãããããã€ã¯ãç§ãšããªç§ããã«ç§ã«å€ããæ¹æ³ã§ã... PHPé¢æ°ã®ååŒã³åºãäžã«ãæãéèŠãªæ瀺ã®ã¿ã瀺ããããšã«æ³šæããŠãã ããã ãã®åŸãããã«èå³æ·±ãããšãèµ·ãããŸãã ãŸãã strlenïŒïŒã®å Žåããæçšãªäœæ¥ããå®è¡ããã®ã¯1è¡ã®ã¿ã§ãããé¢æ°åŒã³åºãã倧éã«æºåããããã®ä»éããæé ã¯ã³ãŒãã®ãæçšãªãéšåããã倧ããããšã«æ³šæããŠãã ããã ãã ããã»ãšãã©ã®å Žåããã€ãã£ãé¢æ°ã³ãŒãã¯ãè£å©ããšã³ãžã³ã³ãŒããããããã©ãŒãã³ã¹ã«åœ±é¿ããŸãã
PHP 7ã®é¢æ°åŒã³åºãã«é¢é£ããPHPã³ãŒãã®äžéšã¯ãããã©ãŒãã³ã¹ãæ¹åããããã«åèšèšãããŸããã ãã ããããã¯çµããã«ã¯ã»ã©é ããã®ã§ãããPHPã®ãœãŒã¹ã³ãŒãã¯æ°ãããªãªãŒã¹ããšã«è€æ°åæé©åãããŸãã å€ãããŒãžã§ã³ã¯å¿ãããããé¢æ°åŒã³åºãã¯5.3ãã5.5ã®ããŒãžã§ã³ã§æé©åãããŸããã ããšãã°ãããŒãžã§ã³5.4ãã5.5ã§ã¯ãäºææ§ãç¶æããªããã¹ã¿ãã¯ãã¬ãŒã ãèšç®ããã³äœæããæ¹æ³ãå€æŽãããŸããã èå³æ·±ãããšã«ãã©ã³ã¿ã€ã ã¢ãžã¥ãŒã«ã®å€æŽãšã ããŒãžã§ã³5.5ã§äœæãããé¢æ°ã®åŒã³åºãæ¹æ³ãš5.4ãæ¯èŒã§ããŸãã
ç§ã¯åŒ·èª¿ãããïŒäžèšã®ãã¹ãŠã¯PHPãæªãããšãæå³ãããã®ã§ã¯ãããŸããã ãã®èšèªã¯20幎ééçºãããŠãããå€ãã®éåžžã«æèœã®ããããã°ã©ããŒããœãŒã¹ã³ãŒãã«åãçµãã§ããŸããã ãã®æéãäœåºŠãåŠçãããæé©åããã³æ¹åãããŸããã ããã¯ãä»æ¥PHPã䜿çšããããŸããŸãªãããžã§ã¯ãã§åªããå šäœçãªããã©ãŒãã³ã¹ãçºæ®ãããšããäºå®ã«ãã£ãŠèšŒæãããŠããŸãã
issetïŒïŒã¯ã©ãã§ããïŒ
ããã¯é¢æ°ã§ã¯ãªããæ¬åŒ§ã¯å¿ ããããé¢æ°åŒã³åºãããæå³ããããã§ã¯ãããŸããã issetïŒïŒã¯ ãZendä»®æ³ãã·ã³ã®ç¹å¥ãªãªãã³ãŒãïŒISSET_ISEMPTYïŒã«å«ãŸããŠããŸããããã¯ãé¢æ°åŒã³åºããéå§ãããé¢é£ããé 延ã®åœ±é¿ãåããŸããã issetïŒïŒã¯ããã€ãã®ã¿ã€ãã®ãã©ã¡ãŒã¿ãŒã䜿çšã§ãããããZendä»®æ³ãã·ã³ã®ã³ãŒãã¯éåžžã«é·ããªããŸãã ãã ãããªãã»ãããã©ã¡ãŒã¿ã«é¢é£ããéšåã®ã¿ãæ®ããšã次ã®ãããªçµæã«ãªããŸãã
ZEND_VM_HELPER_EX(zend_isset_isempty_dim_prop_obj_handler, VAR|UNUSED|CV, CONST|TMP|VAR|CV, int prop_dim) { USE_OPLINE zend_free_op free_op1, free_op2; zval *container; zval **value = NULL; int result = 0; ulong hval; zval *offset; SAVE_OPLINE(); container = GET_OP1_OBJ_ZVAL_PTR(BP_VAR_IS); offset = GET_OP2_ZVAL_PTR(BP_VAR_R); /* ... code pruned ... */ } else if (Z_TYPE_P(container) == IS_STRING && !prop_dim) { /* string offsets */ zval tmp; /* ... code pruned ... */ if (Z_TYPE_P(offset) == IS_LONG) { /* we passed an integer as offset */ if (opline->extended_value & ZEND_ISSET) { if (offset->value.lval >= 0 && offset->value.lval < Z_STRLEN_P(container)) { result = 1; } } else /* if (opline->extended_value & ZEND_ISEMPTY) */ { if (offset->value.lval >= 0 && offset->value.lval < Z_STRLEN_P(container) && Z_STRVAL_P(container)[offset->value.lval] != '0') { result = 1; } } } FREE_OP2(); } else { FREE_OP2(); } Z_TYPE(EX_T(opline->result.var).tmp_var) = IS_BOOL; if (opline->extended_value & ZEND_ISSET) { Z_LVAL(EX_T(opline->result.var).tmp_var) = result; } else { Z_LVAL(EX_T(opline->result.var).tmp_var) = !result; } FREE_OP1_VAR_PTR(); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); }
å€æ°ã®æ±ºå®ç¹ãåé€ããå ŽåïŒã³ã³ã¹ãã©ã¯ãã®å Žå ïŒããã¡ã€ã³ãèšç®ã¢ã«ãŽãªãºã ã¯æ¬¡ã®ããã«è¡šçŸã§ããŸãã
if (offset->value.lval >= 0 && offset->value.lval < Z_STRLEN_P(container))
ãªãã»ããããŒããã倧ããïŒ issetïŒ$ a [-42]ïŒãæå³ããªãïŒãå³å¯ã«è¡ã®é·ãããçãå Žåãçµæã¯1ãšèŠãªãããŸãããã®åŸãæŒç®ã®çµæã¯ããŒã«å€TRUEã«ãªããŸãã é·ãã®èšç®ã«ã€ããŠå¿é ããå¿ èŠã¯ãããŸãããZ_STRLEN_PïŒã³ã³ããïŒã¯äœãèšç®ããŸããã PHPã¯ãã§ã«æååã®é·ããç¥ã£ãŠããããšã«æ³šæããŠãã ããã Z_STRLEN_PïŒã³ã³ããïŒã¯ ããã®å€ãã¡ã¢ãªã«èªã¿èŸŒãã ãã§ãããã»ããµãªãœãŒã¹ãã»ãšãã©æ¶è²»ããŸããã
ããã§ãæååãªãã»ããã®äœ¿çšã«é¢ããŠã strlenïŒïŒåŒã³åºãã®åŠçã«ã¯issetïŒïŒãããå€ãã®èšç®ãªãœãŒã¹ãå¿ èŠã«ãªãçç±ãããããŸããã åŸè ã¯å®è³ªçã«ãç°¡åãã§ãã å€æ°ã®æ¡ä»¶ä»ãifã¹ããŒãã¡ã³ããæããªãã§ãã ãã;ããã¯Cã³ãŒãã®æãé£ããéšåã§ã¯ãããŸããã ããã«ãCã³ã³ãã€ã©ã䜿çšããŠæé©åã§ããŸãã ãã³ãã©ã³ãŒãissetïŒïŒã¯ãåŸã§ååŸããããã«ãããã·ã¥ããŒãã«ã調ã¹ããè€éãªãã§ãã¯ãå®è¡ãããã¹ã¿ãã¯ãã¬ãŒã ã®1ã€ã«ãã€ã³ã¿ãå²ãåœãŠãŸããã ãã®ã³ãŒãã¯ãäžè¬çãªé¢æ°åŒã³åºãã³ãŒããããã¯ããã«è»œéã§ãããã¡ã¢ãªãžã®ã¢ã¯ã»ã¹é »åºŠã¯ã¯ããã«äœããªããŸãïŒãããæãéèŠãªãã€ã³ãã§ãïŒã ãŸãããã®ãããªè¡ã®è€æ°ã®å®è¡ãã«ãŒããããšãããã©ãŒãã³ã¹ãå€§å¹ ã«åäžããŸãã ãã¡ããã strlenïŒïŒãšissetïŒïŒã®1åã®å埩ã®çµæã¯ããã»ã©å€ãããŸãã-çŽ5ããªç§ã§ãã ãããã50,000åã®å埩ãå®è¡ãããš...
ãŸãã issetïŒïŒãšemptyïŒïŒã® ãœãŒã¹ã³ãŒã ã¯ã»ãŒåãã§ããããšã«æ³šæããŠãã ããã è¡ãªãã»ããã®å Žåã 空ã®ïŒïŒã¯ãè¡ã®æåã®æåã0ã§ãªãå Žåãè¿œå ã®èªã¿åãã ããisset ïŒïŒãšç°ãªããŸããempty ïŒïŒããã³issetïŒïŒã³ãŒãã¯ã»ãŒåãã§ããããã emptyïŒïŒã¯åãããã«è¡šç€ºãããŸãissetïŒïŒãšããŠã®ããã©ãŒãã³ã¹ïŒäž¡æ¹ãåããã©ã¡ãŒã¿ãŒã§äœ¿çšãããå ŽåïŒã
OPCacheãã©ã®ããã«åœ¹ç«ã€ã
èŠããã«ãäœããããŸããã
OPCacheã¯ã³ãŒããæé©åããŸãã ããã¯ãã¬ãŒã³ããŒã·ã§ã³ã§èŠã€ããããšãã§ããŸã ã strlenïŒïŒãissetïŒïŒã«åãæ¿ããæé©åãã¹ãè¿œå ããããšã¯å¯èœãã©ãããšããå°ããããŸãã ããããããã¯äžå¯èœã§ãã
OPCacheæé©åãã¹ã¯ãå ±æã¡ã¢ãªã«é 眮ãããåã«OPArrayã«å®è£ ãããŸãã ããã¯å®è¡æã§ã¯ãªãã³ã³ãã€ã«æã«çºçããŸãã ã³ã³ãã€ã«æã«strlenïŒïŒã«æž¡ãããå€æ°ãæååã§ããããšãã©ã®ããã«ããŠç¥ãããšãã§ããŸããïŒ ããã¯PHPã®æ¢ç¥ã®åé¡ã§ãããHHVM / Hackã§éšåçã«è§£æ±ºãããŠããŸãã PHPã§å³å¯ãªåä»ãã䜿çšããŠå€æ°ãèšè¿°ããå Žåãã³ã³ãã€ã©ã®ãã¹äžã«ãïŒä»®æ³ãã·ã³ã®ããã«ïŒã¯ããã«å€ãã®ãã®ãæé©åã§ããŸãã PHPã¯åçèšèªã§ãããããã³ã³ãã€ã«æã«ã¯ã»ãšãã©äœãããããŸããã OPCacheã¯ãã³ã³ãã€ã«ãéå§ãããæç¹ã§ç¥ãããŠããéçãªãã®ã®ã¿ãæé©åã§ããŸãã ããšãã°ãããã¯ïŒ
if (strlen("foo") > 8) { /* do domething */ } else { /* do something else */ }
ã³ã³ãã€ã«æã«ã¯ãæååãfooãã®é·ãã8以äžã§ããããšãããã£ãŠããããããã¹ãŠã®ãªãã³ãŒãifïŒïŒãç Žæ£ããifæ§é ããelseéšåã®ã¿ãæ®ãããšãã§ããŸãã
if (strlen($a) > 8) { /* do domething */ } else { /* do something else */ }
ãããã $ aãšã¯äœã§ããïŒ ååšããŸããïŒ ããã¯æååã§ããïŒ ãªããã£ãã€ã¶ãŒãåæ ŒãããŸã§ãããããã¹ãŠã®è³ªåã«çããããšã¯ã§ããŸãããããã¯ãä»®æ³ãã·ã³ã®å®è¡ã¢ãžã¥ãŒã«ã®ã¿ã¹ã¯ã§ãã ã³ã³ãã€ã«æã«æœè±¡æ§é ãåŠçããŸããå¿ èŠãªã¡ã¢ãªã®ã¿ã€ããšéã¯å®è¡æã«ããããŸãã
OPCacheã¯å€ãã®ããšãæé©åããŸãããPHPã®æ§è³ªã«ããããã¹ãŠãæé©åããããšã¯ã§ããŸããã , Java . , PHP . read-only:
class Foo { public read-only $a = "foo"; }
, . , $a . , , - , OPCache. , , OPCache , , .
, - . . Blackfire , , . , . , . , , , , .
: PHP , . PHP- â , , . . , , . , . PHP , foreach() , opcode. while for , .
, , , - .
phpversion() => use the PHP_VERSION constant php_uname() => use the PHP_OS constant php_sapi_name() => use the PHP_SAPI constant time() => read $_SERVER['REQUEST_TIME'] session_id() => use the SID constant
, .
, , :
function foo() { bar(); }
:
function foo() { call_user_func_array('bar', func_get_args()); }
, , - - - . , .
, . .
Blackfire , . ( GUI ): , , , / , , , foreach() .. ãªã©
, . , - . PHP ORM, , HTTP- . , . , : Java, Go , , â C/C++ (Java Go ).