@@ -2515,6 +2515,67 @@ ZEND_VM_C_LABEL(exit_assign_obj):
2515
2515
ZEND_VM_NEXT_OPCODE_EX (1 , 2 );
2516
2516
}
2517
2517
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
+
2518
2579
/* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CONST|VAR) */
2519
2580
ZEND_VM_HANDLER (25 , ZEND_ASSIGN_STATIC_PROP , ANY , ANY , CACHE_SLOT , SPEC (OP_DATA = CONST |TMP |VAR |CV ))
2520
2581
{
0 commit comments