Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[RFC] Add Random Extension #7079

Closed
wants to merge 15 commits into from
Closed

Conversation

zeriyoshi
Copy link
Contributor

@zeriyoshi zeriyoshi commented May 31, 2021

Added Random extension and many classes.

RFC is now available.
https://wiki.php.net/rfc/rng_extension

Available Algorithm's

  • XorShift128+ (Random\NumberGenerator\XorShift128Plus)
  • MT19937 (Random\NumberGenerator\MT19937)
  • secure (uses php_random_byte() internally) (Random\NumberGenerator\Secure)

@krakjoe krakjoe added the RFC label May 31, 2021
@zeriyoshi zeriyoshi force-pushed the random_class branch 2 times, most recently from 85f6c30 to 01fc380 Compare May 31, 2021 11:04
@drupol

This comment has been minimized.

@zeriyoshi

This comment has been minimized.

@drupol

This comment has been minimized.

@zeriyoshi

This comment has been minimized.

@drupol

This comment has been minimized.

@kamil-tekiela

This comment has been minimized.

@drupol

This comment has been minimized.

@nikic
Copy link
Member

nikic commented May 31, 2021

Please keep design discussions to the thread on the PHP internals mailing list (https://externals.io/message/114561). Otherwise relevant parties may not be aware of it.

@drupol
Copy link

drupol commented May 31, 2021

Please keep design discussions to the thread on the PHP internals mailing list (https://externals.io/message/114561). Otherwise relevant parties may not be aware of it.

Sorry it's my first time commenting here, I didn't know that details and will comply. Sorry about that.

@zeriyoshi
Copy link
Contributor Author

@nikic @drupol @kamil-tekiela
I'm sorry. I was on the verge of posting to the Internals ML.
I will post to Internals again after I sort out the implementation and RFCs.

I would be happy to have future design discussions in the following threads.

https://externals.io/message/114561

@zeriyoshi zeriyoshi changed the title [RFC] Add Random class [RFC] Add Random Extension Jun 26, 2021
Copy link
Contributor

@TysonAndre TysonAndre left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

EXTENSION("random" should create module symbols with random, not php_random (excluding static methods or C functions exposed to other modules in the header)

(both by convention and to avoid build issues - I forget exactly where it's important)

@@ -0,0 +1,67 @@
/*
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The file name is wrong and will cause build issues, I think. This should be named php_random.h instead. See build/print_include.awk

../php-src/ext/tokenizer/php_tokenizer.h
21:#define phpext_tokenizer_ptr &tokenizer_module_entry

../php-src/ext/xsl/php_xsl.h
21:#define phpext_xsl_ptr &xsl_module_entry

Copy link
Contributor Author

@zeriyoshi zeriyoshi Jun 27, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If changed to php_random.h, the include guard conflicts with php_random.h in ext/standard.
Use PHP_RANDOM_H_MODULE for the include guard only.

#ifndef PHP_RANDOM_MODULE_H
#define PHP_RANDOM_MODULE_H

extern zend_module_entry php_random_module_entry;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: I don't remember if this affects the build (it might or might not), but the conventional name would be random_module_entry here and below.

(E.g. if php looks for a symbol with that name when loading a shared library - it very likely might)

extern zend_module_entry php_random_module_entry;
#define phpext_random_ptr &php_random_module_entry

extern PHPAPI zend_class_entry *php_random_ce_Random_NumberGenerator_RandomNumberGenerator;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: I think random_ce_ would be shorter and follow conventions, e.g. spl starts with spl.

The other names in this header are fine.

extern PHPAPI zend_class_entry *spl_ce_SplFixedArray;

/* }}} */

/* {{{ php_random_module_entry */
zend_module_entry php_random_module_entry = {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same here for random_module_entry, both in PHP_MINIT(random) and PHP_MINIT_FUNCTION(random)

}

static inline zend_object *php_random_rng_common_init(zend_class_entry *ce, const php_random_rng_algo *algo, const zend_object_handlers *handlers) {
php_random_rng *rng = zend_object_alloc(sizeof(php_random_rng), ce);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems to be correct - zend_object_alloc is zeroing out state (i.e. setting it to NULL)

/* Allocates object type and zeros it, but not the standard zend_object and properties.
 * Standard object MUST be initialized using zend_object_std_init().
 * Properties MUST be initialized using object_properties_init(). */
static zend_always_inline void *zend_object_alloc(size_t obj_size, zend_class_entry *ce) {
	void *obj = emalloc(obj_size + zend_object_properties_size(ce));
	memset(obj, 0, obj_size - sizeof(zend_object));
	return obj;
}

Copy link
Contributor Author

@zeriyoshi zeriyoshi Jul 1, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, but I'm still getting unintended Valgrind warnings.
Also, the ZTS build on Windows seems to be SEGV on during testing. I do not have a Windows environment, but will continue to try to resolve this.

php_random_rng *rng = php_random_rng_from_obj(object);

if (rng->state) {
efree(rng->state);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could set rng->state to NULL just in case - I think the object can be referenced even after __destruct is called.

I don't think that's the issue, though

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The object can't be referenced after free_obj, only dtor_obj.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, I'll leave this as is.

ZEND_PARSE_PARAMETERS_END();

if (!rng) {
rng = php_random_rng_xorshfit128plus_new(php_random_ce_Random_NumberGenerator_XorShift128Plus);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
rng = php_random_rng_xorshfit128plus_new(php_random_ce_Random_NumberGenerator_XorShift128Plus);
rng = php_random_rng_xorshift128plus_new(php_random_ce_Random_NumberGenerator_XorShift128Plus);

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed.

return php_random_rng_next(random->rng, truncate);
}

rng = Z_OBJ_P(zend_read_property(random->std.ce, &random->std, "rng", sizeof("rng") - 1, 0, NULL));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should add a check that the zval from zend_read_property is IS_OBJECT.

I'm not sure if using a property is efficient, though - e.g. adding a zend_object *obj to php_random instead would make that a simple pointer lookup.

Also, with Closure->bindTo, it's possible for userland code to call unset($this->std), I think?

For the alternative, it's possible to override get_properties, get_gc, etc. handlers. Look at SplDoublyLinkedList as an example in ext/spl/spl_dll.c

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you. I'll take a look.

return ret;
}

uint64_t php_random_next(php_random *random, bool truncate)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
uint64_t php_random_next(php_random *random, bool truncate)
PHPAPI uint64_t php_random_next(php_random *random, bool truncate)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed

ext/random/random.stub.php Outdated Show resolved Hide resolved
Copy link
Member

@nikic nikic left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(just scrolling through)

ext/random/random.c Outdated Show resolved Hide resolved
ext/random/random.c Outdated Show resolved Hide resolved
zend_string *rng_fname;
zend_function *rng_func;

if (random->rng) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that userland should also be handled via php_random_rng_algo. It should be created on construction, and the state can cache the zend_function for generate for example. This will make it more efficient, and also make your implementation uniform, because you don't need to distinguish between the userland/internal cases. This is a benefit of the Random class vs the previous free functions, as you can do work during construction now.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now that Random is a final class, this is a very reasonable opinion.
Thanks. I will implement.

php_random_rng *rng = php_random_rng_from_obj(object);

if (rng->state) {
efree(rng->state);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The object can't be referenced after free_obj, only dtor_obj.

ext/random/random.c Outdated Show resolved Hide resolved
ext/random/random.c Outdated Show resolved Hide resolved
ext/random/random.c Outdated Show resolved Hide resolved
@nikic nikic added this to the PHP 8.2 milestone Jul 19, 2021
@zeriyoshi
Copy link
Contributor Author

Create an updated RFC and a new Pull-Request. Thanks.

@zeriyoshi zeriyoshi closed this Sep 2, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

6 participants