@@ -2515,6 +2515,67 @@ ZEND_VM_C_LABEL(exit_assign_obj):
25152515 ZEND_VM_NEXT_OPCODE_EX (1 , 2 );
25162516}
25172517
2518+ ZEND_VM_TYPE_SPEC_HANDLER (ZEND_ASSIGN_OBJ , (op -> extended_value & 1 ) != 0 , ZEND_ASSIGN_OBJ_CORRECTLY_TYPED , UNUSED |VAR |THIS |CV , CONST , CACHE_SLOT , SPEC (OP_DATA = CONST |TMP |VAR |CV ))
2519+ {
2520+ USE_OPLINE
2521+ zval * object , * value ;
2522+ zend_object * zobj ;
2523+ zend_string * name ;
2524+ zend_refcounted * garbage = NULL ;
2525+
2526+ SAVE_OPLINE ();
2527+ object = GET_OP1_OBJ_ZVAL_PTR_PTR_UNDEF (BP_VAR_W );
2528+ value = GET_OP_DATA_ZVAL_PTR (BP_VAR_R );
2529+
2530+ // TODO: get rid of this?
2531+ if (OP1_TYPE != IS_UNUSED && UNEXPECTED (Z_TYPE_P (object ) != IS_OBJECT )) {
2532+ if (Z_ISREF_P (object ) && Z_TYPE_P (Z_REFVAL_P (object )) == IS_OBJECT ) {
2533+ object = Z_REFVAL_P (object );
2534+ ZEND_VM_C_GOTO (assign_object );
2535+ }
2536+ zend_throw_non_object_error (object , GET_OP2_ZVAL_PTR (BP_VAR_R ) OPLINE_CC EXECUTE_DATA_CC );
2537+ value = & EG (uninitialized_zval );
2538+ ZEND_VM_C_GOTO (free_and_exit_assign_obj );
2539+ }
2540+
2541+ ZEND_VM_C_LABEL (assign_object ):
2542+ zobj = Z_OBJ_P (object );
2543+ if (EXPECTED (zobj -> ce == CACHED_PTR (opline -> extended_value & ~1 ))) {
2544+ void * * cache_slot = CACHE_ADDR (opline -> extended_value & ~1 );
2545+ uintptr_t prop_offset = (uintptr_t )CACHED_PTR_EX (cache_slot + 1 );
2546+ zval * property_val = OBJ_PROP (zobj , prop_offset );
2547+
2548+ ZEND_ASSERT (IS_VALID_PROPERTY_OFFSET (prop_offset ));
2549+
2550+ if (Z_TYPE_P (property_val ) != IS_UNDEF ) {
2551+ value = zend_assign_to_variable_ex (property_val , value , OP_DATA_TYPE , EX_USES_STRICT_TYPES (), & garbage );
2552+ if (UNEXPECTED (RETURN_VALUE_USED (opline ))) {
2553+ ZVAL_COPY (EX_VAR (opline -> result .var ), value );
2554+ }
2555+ ZEND_VM_C_GOTO (exit_assign_obj );
2556+ }
2557+ }
2558+ name = Z_STR_P (GET_OP2_ZVAL_PTR (BP_VAR_R ));
2559+
2560+ ZEND_ASSERT (!Z_ISREF_P (value ));
2561+
2562+ value = zobj -> handlers -> write_property (zobj , name , value , (OP2_TYPE == IS_CONST ) ? CACHE_ADDR (opline -> extended_value & ~1 ) : NULL );
2563+
2564+ ZEND_VM_C_LABEL (free_and_exit_assign_obj ):
2565+ if (UNEXPECTED (RETURN_VALUE_USED (opline )) && value ) {
2566+ ZVAL_COPY_DEREF (EX_VAR (opline -> result .var ), value );
2567+ }
2568+ FREE_OP_DATA ();
2569+ ZEND_VM_C_LABEL (exit_assign_obj ):
2570+ if (garbage ) {
2571+ GC_DTOR_NO_REF (garbage );
2572+ }
2573+ FREE_OP2 ();
2574+ FREE_OP1 ();
2575+ /* assign_obj has two opcodes! */
2576+ ZEND_VM_NEXT_OPCODE_EX (1 , 2 );
2577+ }
2578+
25182579/* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CONST|VAR) */
25192580ZEND_VM_HANDLER (25 , ZEND_ASSIGN_STATIC_PROP , ANY , ANY , CACHE_SLOT , SPEC (OP_DATA = CONST |TMP |VAR |CV ))
25202581{
0 commit comments